agora inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH 3/5] Fix handling of NULLs in MCV items and constants
180+ messages / 5 participants
[nested] [flat]

* [PATCH 3/5] Fix handling of NULLs in MCV items and constants
@ 2019-07-15 00:00  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Tomas Vondra @ 2019-07-15 00:00 UTC (permalink / raw)

There were two issues in how the extended statistics handled NULL values
in opclauses. Firstly, the code was oblivious to the possibility that
Const may be NULL (constisnull=true) in which case the constvalue is
undefined. We need to treat this as a mismatch, and not call the proc.

Secondly, the MCV item itself may contain NULL values too - the code
already did check that, and updated the match bitmap accordingly, but
failed to ensure we won't call the operator procedure anyway.

This fixes both issues by extending the existing check so that it looks
at constisnull too, and making sure it skips calling the procedure.

Discussion: https://postgr.es/m/8736jdhbhc.fsf%40ansel.ydns.eu
---
 src/backend/statistics/mcv.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c
index 865981bbb4..77daa647e2 100644
--- a/src/backend/statistics/mcv.c
+++ b/src/backend/statistics/mcv.c
@@ -1593,12 +1593,18 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
 					MCVItem    *item = &mcvlist->items[i];
 
 					/*
-					 * For AND-lists, we can also mark NULL items as 'no
-					 * match' (and then skip them). For OR-lists this is not
-					 * possible.
+					 * When the MCV item or the Const value is NULL we can treat
+					 * this as a mismatch. We must not call the operator proc
+					 * because of strictness.
 					 */
-					if ((!is_or) && item->isnull[idx])
-						matches[i] = false;
+					if (item->isnull[idx] || cst->constisnull)
+					{
+						/* we only care about AND, because OR can't change */
+						if (!is_or)
+							matches[i] = false;
+
+						continue;
+					}
 
 					/* skip MCV items that were already ruled out */
 					if ((!is_or) && (matches[i] == false))
-- 
2.20.1


--ztxiowpcs6gwvnvh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
 filename="0004-Refactor-simplify-evaluation-of-MCV-bitmap.patch"



^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH] Track DEALLOCATE statements in pg_stat_activity
@ 2023-08-14 10:59  Dagfinn Ilmari Mannsåker <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Dagfinn Ilmari Mannsåker @ 2023-08-14 10:59 UTC (permalink / raw)

Treat the statement name as a constant when jumbling.
---
 .../pg_stat_statements/expected/utility.out   | 40 +++++++++++++++++++
 .../pg_stat_statements/pg_stat_statements.c   |  8 +---
 contrib/pg_stat_statements/sql/utility.sql    | 13 ++++++
 src/backend/parser/gram.y                     |  4 ++
 src/include/nodes/parsenodes.h                |  6 ++-
 5 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/contrib/pg_stat_statements/expected/utility.out b/contrib/pg_stat_statements/expected/utility.out
index 93735d5d85..3681374869 100644
--- a/contrib/pg_stat_statements/expected/utility.out
+++ b/contrib/pg_stat_statements/expected/utility.out
@@ -472,6 +472,46 @@ SELECT pg_stat_statements_reset();
  
 (1 row)
 
+-- Execution statements
+SELECT 1 as a;
+ a 
+---
+ 1
+(1 row)
+
+PREPARE stat_select AS SELECT $1 AS a;
+EXECUTE stat_select (1);
+ a 
+---
+ 1
+(1 row)
+
+DEALLOCATE stat_select;
+PREPARE stat_select AS SELECT $1 AS a;
+EXECUTE stat_select (2);
+ a 
+---
+ 2
+(1 row)
+
+DEALLOCATE PREPARE stat_select;
+DEALLOCATE ALL;
+DEALLOCATE PREPARE ALL;
+SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C";
+ calls | rows |                 query                 
+-------+------+---------------------------------------
+     4 |    0 | DEALLOCATE $1
+     2 |    2 | PREPARE stat_select AS SELECT $1 AS a
+     1 |    1 | SELECT $1 as a
+     1 |    1 | SELECT pg_stat_statements_reset()
+(4 rows)
+
+SELECT pg_stat_statements_reset();
+ pg_stat_statements_reset 
+--------------------------
+ 
+(1 row)
+
 -- SET statements.
 -- These use two different strings, still they count as one entry.
 SET work_mem = '1MB';
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 55b957d251..06b65aeef5 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -104,8 +104,7 @@ static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100;
  * ignores.
  */
 #define PGSS_HANDLED_UTILITY(n)		(!IsA(n, ExecuteStmt) && \
-									!IsA(n, PrepareStmt) && \
-									!IsA(n, DeallocateStmt))
+									!IsA(n, PrepareStmt))
 
 /*
  * Extension version number, for supporting older extension versions' objects
@@ -830,8 +829,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate)
 
 	/*
 	 * Clear queryId for prepared statements related utility, as those will
-	 * inherit from the underlying statement's one (except DEALLOCATE which is
-	 * entirely untracked).
+	 * inherit from the underlying statement's one.
 	 */
 	if (query->utilityStmt)
 	{
@@ -1116,8 +1114,6 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
 	 * calculated from the query tree) would be used to accumulate costs of
 	 * ensuing EXECUTEs.  This would be confusing, and inconsistent with other
 	 * cases where planning time is not included at all.
-	 *
-	 * Likewise, we don't track execution of DEALLOCATE.
 	 */
 	if (pgss_track_utility && pgss_enabled(exec_nested_level) &&
 		PGSS_HANDLED_UTILITY(parsetree))
diff --git a/contrib/pg_stat_statements/sql/utility.sql b/contrib/pg_stat_statements/sql/utility.sql
index 87666d9135..5f7d4a467f 100644
--- a/contrib/pg_stat_statements/sql/utility.sql
+++ b/contrib/pg_stat_statements/sql/utility.sql
@@ -237,6 +237,19 @@ DROP DOMAIN domain_stats;
 SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C";
 SELECT pg_stat_statements_reset();
 
+-- Execution statements
+SELECT 1 as a;
+PREPARE stat_select AS SELECT $1 AS a;
+EXECUTE stat_select (1);
+DEALLOCATE stat_select;
+PREPARE stat_select AS SELECT $1 AS a;
+EXECUTE stat_select (2);
+DEALLOCATE PREPARE stat_select;
+DEALLOCATE ALL;
+DEALLOCATE PREPARE ALL;
+SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C";
+SELECT pg_stat_statements_reset();
+
 -- SET statements.
 -- These use two different strings, still they count as one entry.
 SET work_mem = '1MB';
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index b3bdf947b6..680c7f3683 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11936,6 +11936,7 @@ DeallocateStmt: DEALLOCATE name
 						DeallocateStmt *n = makeNode(DeallocateStmt);
 
 						n->name = $2;
+						n->location = @2;
 						$$ = (Node *) n;
 					}
 				| DEALLOCATE PREPARE name
@@ -11943,6 +11944,7 @@ DeallocateStmt: DEALLOCATE name
 						DeallocateStmt *n = makeNode(DeallocateStmt);
 
 						n->name = $3;
+						n->location = @3;
 						$$ = (Node *) n;
 					}
 				| DEALLOCATE ALL
@@ -11950,6 +11952,7 @@ DeallocateStmt: DEALLOCATE name
 						DeallocateStmt *n = makeNode(DeallocateStmt);
 
 						n->name = NULL;
+						n->location = -1;
 						$$ = (Node *) n;
 					}
 				| DEALLOCATE PREPARE ALL
@@ -11957,6 +11960,7 @@ DeallocateStmt: DEALLOCATE name
 						DeallocateStmt *n = makeNode(DeallocateStmt);
 
 						n->name = NULL;
+						n->location = -1;
 						$$ = (Node *) n;
 					}
 		;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 2565348303..b7aeebe3b4 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -3925,8 +3925,10 @@ typedef struct ExecuteStmt
 typedef struct DeallocateStmt
 {
 	NodeTag		type;
-	char	   *name;			/* The name of the plan to remove */
-	/* NULL means DEALLOCATE ALL */
+	/* The name of the plan to remove.  NULL means DEALLOCATE ALL. */
+	char	   *name pg_node_attr(query_jumble_ignore);
+	/* token location, or -1 if unknown */
+	int			location pg_node_attr(query_jumble_location);
 } DeallocateStmt;
 
 /*
-- 
2.39.2


--=-=-=--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH] Track DEALLOCATE statements in pg_stat_activity
@ 2023-08-14 10:59  Dagfinn Ilmari Mannsåker <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Dagfinn Ilmari Mannsåker @ 2023-08-14 10:59 UTC (permalink / raw)

Treat the statement name as a constant when jumbling.
---
 .../pg_stat_statements/expected/utility.out   | 40 +++++++++++++++++++
 .../pg_stat_statements/pg_stat_statements.c   |  8 +---
 contrib/pg_stat_statements/sql/utility.sql    | 13 ++++++
 src/backend/parser/gram.y                     |  4 ++
 src/include/nodes/parsenodes.h                |  6 ++-
 5 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/contrib/pg_stat_statements/expected/utility.out b/contrib/pg_stat_statements/expected/utility.out
index 93735d5d85..3681374869 100644
--- a/contrib/pg_stat_statements/expected/utility.out
+++ b/contrib/pg_stat_statements/expected/utility.out
@@ -472,6 +472,46 @@ SELECT pg_stat_statements_reset();
  
 (1 row)
 
+-- Execution statements
+SELECT 1 as a;
+ a 
+---
+ 1
+(1 row)
+
+PREPARE stat_select AS SELECT $1 AS a;
+EXECUTE stat_select (1);
+ a 
+---
+ 1
+(1 row)
+
+DEALLOCATE stat_select;
+PREPARE stat_select AS SELECT $1 AS a;
+EXECUTE stat_select (2);
+ a 
+---
+ 2
+(1 row)
+
+DEALLOCATE PREPARE stat_select;
+DEALLOCATE ALL;
+DEALLOCATE PREPARE ALL;
+SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C";
+ calls | rows |                 query                 
+-------+------+---------------------------------------
+     4 |    0 | DEALLOCATE $1
+     2 |    2 | PREPARE stat_select AS SELECT $1 AS a
+     1 |    1 | SELECT $1 as a
+     1 |    1 | SELECT pg_stat_statements_reset()
+(4 rows)
+
+SELECT pg_stat_statements_reset();
+ pg_stat_statements_reset 
+--------------------------
+ 
+(1 row)
+
 -- SET statements.
 -- These use two different strings, still they count as one entry.
 SET work_mem = '1MB';
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 55b957d251..06b65aeef5 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -104,8 +104,7 @@ static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100;
  * ignores.
  */
 #define PGSS_HANDLED_UTILITY(n)		(!IsA(n, ExecuteStmt) && \
-									!IsA(n, PrepareStmt) && \
-									!IsA(n, DeallocateStmt))
+									!IsA(n, PrepareStmt))
 
 /*
  * Extension version number, for supporting older extension versions' objects
@@ -830,8 +829,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate)
 
 	/*
 	 * Clear queryId for prepared statements related utility, as those will
-	 * inherit from the underlying statement's one (except DEALLOCATE which is
-	 * entirely untracked).
+	 * inherit from the underlying statement's one.
 	 */
 	if (query->utilityStmt)
 	{
@@ -1116,8 +1114,6 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
 	 * calculated from the query tree) would be used to accumulate costs of
 	 * ensuing EXECUTEs.  This would be confusing, and inconsistent with other
 	 * cases where planning time is not included at all.
-	 *
-	 * Likewise, we don't track execution of DEALLOCATE.
 	 */
 	if (pgss_track_utility && pgss_enabled(exec_nested_level) &&
 		PGSS_HANDLED_UTILITY(parsetree))
diff --git a/contrib/pg_stat_statements/sql/utility.sql b/contrib/pg_stat_statements/sql/utility.sql
index 87666d9135..5f7d4a467f 100644
--- a/contrib/pg_stat_statements/sql/utility.sql
+++ b/contrib/pg_stat_statements/sql/utility.sql
@@ -237,6 +237,19 @@ DROP DOMAIN domain_stats;
 SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C";
 SELECT pg_stat_statements_reset();
 
+-- Execution statements
+SELECT 1 as a;
+PREPARE stat_select AS SELECT $1 AS a;
+EXECUTE stat_select (1);
+DEALLOCATE stat_select;
+PREPARE stat_select AS SELECT $1 AS a;
+EXECUTE stat_select (2);
+DEALLOCATE PREPARE stat_select;
+DEALLOCATE ALL;
+DEALLOCATE PREPARE ALL;
+SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C";
+SELECT pg_stat_statements_reset();
+
 -- SET statements.
 -- These use two different strings, still they count as one entry.
 SET work_mem = '1MB';
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index b3bdf947b6..680c7f3683 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11936,6 +11936,7 @@ DeallocateStmt: DEALLOCATE name
 						DeallocateStmt *n = makeNode(DeallocateStmt);
 
 						n->name = $2;
+						n->location = @2;
 						$$ = (Node *) n;
 					}
 				| DEALLOCATE PREPARE name
@@ -11943,6 +11944,7 @@ DeallocateStmt: DEALLOCATE name
 						DeallocateStmt *n = makeNode(DeallocateStmt);
 
 						n->name = $3;
+						n->location = @3;
 						$$ = (Node *) n;
 					}
 				| DEALLOCATE ALL
@@ -11950,6 +11952,7 @@ DeallocateStmt: DEALLOCATE name
 						DeallocateStmt *n = makeNode(DeallocateStmt);
 
 						n->name = NULL;
+						n->location = -1;
 						$$ = (Node *) n;
 					}
 				| DEALLOCATE PREPARE ALL
@@ -11957,6 +11960,7 @@ DeallocateStmt: DEALLOCATE name
 						DeallocateStmt *n = makeNode(DeallocateStmt);
 
 						n->name = NULL;
+						n->location = -1;
 						$$ = (Node *) n;
 					}
 		;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 2565348303..b7aeebe3b4 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -3925,8 +3925,10 @@ typedef struct ExecuteStmt
 typedef struct DeallocateStmt
 {
 	NodeTag		type;
-	char	   *name;			/* The name of the plan to remove */
-	/* NULL means DEALLOCATE ALL */
+	/* The name of the plan to remove.  NULL means DEALLOCATE ALL. */
+	char	   *name pg_node_attr(query_jumble_ignore);
+	/* token location, or -1 if unknown */
+	int			location pg_node_attr(query_jumble_location);
 } DeallocateStmt;
 
 /*
-- 
2.39.2


--=-=-=--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 4/4] Add CONCURRENTLY option to REPACK command.
@ 2025-12-04 17:20  Antonin Houska <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Antonin Houska @ 2025-12-04 17:20 UTC (permalink / raw)

The REPACK command copies the relation data into a new file, creates new
indexes and eventually swaps the files. To make sure that the old file does
not change during the copying, the relation is locked in an exclusive mode,
which prevents applications from both reading and writing. (To keep the data
consistent, we'd only need to prevent the applications from writing, but even
reading needs to be blocked before we can swap the files - otherwise some
applications could continue using the old file. Since we should not request a
stronger lock without releasing the weaker one first, we acquire the exclusive
lock in the beginning and keep it till the end of the processing.)

This patch introduces an alternative workflow, which only requires the
exclusive lock when the relation (and index) files are being swapped.
(Supposedly, the swapping should be pretty fast.) On the other hand, when we
copy the data to the new file, we allow applications to read from the relation
and even to write to it.

First, we scan the relation using a "historic snapshot", and insert all the
tuples satisfying this snapshot into the new file.

Second, logical decoding is used to capture the data changes done by
applications during the copying (i.e. changes that do not satisfy the historic
snapshot mentioned above), and those are applied to the new file before we
acquire the exclusive lock that we need to swap the files. (Of course, more
data changes can take place while we are waiting for the lock - these will be
applied to the new file after we have acquired the lock, before we swap the
files.)

Since the logical decoding system, during its startup, waits until all the
transactions which already have XID assigned have finished, there is a risk of
deadlock if a transaction that already changed anything in the database tries
to acquire a conflicting lock on the table REPACK CONCURRENTLY is working
on. As an example, consider transaction running CREATE INDEX command on the
table that is being REPACKed CONCURRENTLY. On the other hand, DML commands
(INSERT, UPDATE, DELETE) are not a problem as their lock does not conflict
with REPACK CONCURRENTLY.

The current approach is that we accept the risk. If we tried to avoid it, it'd
be necessary to unlock the table before the logical decoding is setup and lock
it again afterwards. Such temporary unlocking would imply re-checking if the
table still meets all the requirements for REPACK CONCURRENTLY.

Like the existing implementation of REPACK, the variant with the CONCURRENTLY
option also requires an extra space for the new relation and index files
(which coexist with the old files for some time). In addition, the
CONCURRENTLY option might introduce a lag in releasing WAL segments for
archiving / recycling. This is due to the decoding of the data changes done by
applications concurrently. When copying the table contents into the new file,
we check the lag periodically. If it exceeds the size of a WAL segment, we
decode all the available WAL before resuming the copying. (Of course, the
changes are not applied until the whole table contents is copied.) A
background worker might be a better approach for the decoding - let's consider
implementing it in the future.

The WAL records produced by running DML commands on the new relation do not
contain enough information to be processed by the logical decoding system. All
we need from the new relation is the file (relfilenode), while the actual
relation is eventually dropped. Thus there is no point in replaying the DMLs
anywhere.
---
 doc/src/sgml/monitoring.sgml                  |   37 +-
 doc/src/sgml/mvcc.sgml                        |   12 +-
 doc/src/sgml/ref/repack.sgml                  |  129 +-
 src/Makefile                                  |    1 +
 src/backend/access/heap/heapam.c              |   34 +-
 src/backend/access/heap/heapam_handler.c      |  227 ++-
 src/backend/access/heap/rewriteheap.c         |    6 +-
 src/backend/access/transam/xact.c             |   11 +-
 src/backend/catalog/system_views.sql          |   19 +-
 src/backend/commands/cluster.c                | 1659 ++++++++++++++++-
 src/backend/commands/matview.c                |    2 +-
 src/backend/commands/tablecmds.c              |    1 +
 src/backend/commands/vacuum.c                 |   12 +-
 src/backend/meson.build                       |    1 +
 src/backend/replication/logical/decode.c      |   93 +
 src/backend/replication/logical/snapbuild.c   |   23 +-
 .../replication/pgoutput_repack/Makefile      |   32 +
 .../replication/pgoutput_repack/meson.build   |   18 +
 .../pgoutput_repack/pgoutput_repack.c         |  248 +++
 .../storage/lmgr/generate-lwlocknames.pl      |    2 +-
 src/backend/utils/cache/relcache.c            |    1 +
 src/backend/utils/time/snapmgr.c              |    3 +-
 src/bin/psql/tab-complete.in.c                |    4 +-
 src/include/access/heapam.h                   |    9 +-
 src/include/access/heapam_xlog.h              |    2 +
 src/include/access/tableam.h                  |   10 +
 src/include/commands/cluster.h                |   90 +-
 src/include/commands/progress.h               |   17 +-
 src/include/replication/snapbuild.h           |    1 +
 src/include/storage/lockdefs.h                |    4 +-
 src/include/utils/snapmgr.h                   |    2 +
 src/test/modules/injection_points/Makefile    |    2 +
 .../injection_points/expected/repack.out      |  113 ++
 .../modules/injection_points/logical.conf     |    1 +
 src/test/modules/injection_points/meson.build |    3 +
 .../injection_points/specs/repack.spec        |  143 ++
 src/test/regress/expected/rules.out           |   19 +-
 src/tools/pgindent/typedefs.list              |    5 +
 38 files changed, 2761 insertions(+), 235 deletions(-)
 create mode 100644 src/backend/replication/pgoutput_repack/Makefile
 create mode 100644 src/backend/replication/pgoutput_repack/meson.build
 create mode 100644 src/backend/replication/pgoutput_repack/pgoutput_repack.c
 create mode 100644 src/test/modules/injection_points/expected/repack.out
 create mode 100644 src/test/modules/injection_points/logical.conf
 create mode 100644 src/test/modules/injection_points/specs/repack.spec

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index b8da77b4d89..7d9e60c1b20 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -6177,14 +6177,35 @@ FROM pg_stat_get_backend_idset() AS backendid;
 
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
-       <structfield>heap_tuples_written</structfield> <type>bigint</type>
+       <structfield>heap_tuples_inserted</structfield> <type>bigint</type>
       </para>
       <para>
-       Number of heap tuples written.
+       Number of heap tuples inserted.
        This counter only advances when the phase is
        <literal>seq scanning heap</literal>,
-       <literal>index scanning heap</literal>
-       or <literal>writing new heap</literal>.
+       <literal>index scanning heap</literal>,
+       <literal>writing new heap</literal>
+       or <literal>catch-up</literal>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>heap_tuples_updated</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Number of heap tuples updated.
+       This counter only advances when the phase is <literal>catch-up</literal>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>heap_tuples_deleted</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Number of heap tuples deleted.
+       This counter only advances when the phase is <literal>catch-up</literal>.
       </para></entry>
      </row>
 
@@ -6265,6 +6286,14 @@ FROM pg_stat_get_backend_idset() AS backendid;
        <command>REPACK</command> is currently writing the new heap.
      </entry>
     </row>
+    <row>
+     <entry><literal>catch-up</literal></entry>
+     <entry>
+       <command>REPACK CONCURRENTLY</command> is currently processing the DML
+       commands that other transactions executed during any of the preceding
+       phase.
+     </entry>
+    </row>
     <row>
      <entry><literal>swapping relation files</literal></entry>
      <entry>
diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml
index 049ee75a4ba..0f5c34af542 100644
--- a/doc/src/sgml/mvcc.sgml
+++ b/doc/src/sgml/mvcc.sgml
@@ -1833,15 +1833,17 @@ SELECT pg_advisory_lock(q.id) FROM
    <title>Caveats</title>
 
    <para>
-    Some DDL commands, currently only <link linkend="sql-truncate"><command>TRUNCATE</command></link> and the
-    table-rewriting forms of <link linkend="sql-altertable"><command>ALTER TABLE</command></link>, are not
+    Some commands, currently only <link linkend="sql-truncate"><command>TRUNCATE</command></link>, the
+    table-rewriting forms of <link linkend="sql-altertable"><command>ALTER
+    TABLE</command></link> and <command>REPACK</command> with
+    the <literal>CONCURRENTLY</literal> option, are not
     MVCC-safe.  This means that after the truncation or rewrite commits, the
     table will appear empty to concurrent transactions, if they are using a
-    snapshot taken before the DDL command committed.  This will only be an
+    snapshot taken before the command committed.  This will only be an
     issue for a transaction that did not access the table in question
-    before the DDL command started &mdash; any transaction that has done so
+    before the command started &mdash; any transaction that has done so
     would hold at least an <literal>ACCESS SHARE</literal> table lock,
-    which would block the DDL command until that transaction completes.
+    which would block the truncating or rewriting command until that transaction completes.
     So these commands will not cause any apparent inconsistency in the
     table contents for successive queries on the target table, but they
     could cause visible inconsistency between the contents of the target
diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml
index 61d5c2cdef1..2765ce4100e 100644
--- a/doc/src/sgml/ref/repack.sgml
+++ b/doc/src/sgml/ref/repack.sgml
@@ -28,6 +28,7 @@ REPACK [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] USING
 
     VERBOSE [ <replaceable class="parameter">boolean</replaceable> ]
     ANALYZE [ <replaceable class="parameter">boolean</replaceable> ]
+    CONCURRENTLY [ <replaceable class="parameter">boolean</replaceable> ]
 
 <phrase>and <replaceable class="parameter">table_and_columns</replaceable> is:</phrase>
 
@@ -54,7 +55,8 @@ REPACK [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] USING
    processes every table and materialized view in the current database that
    the current user has the <literal>MAINTAIN</literal> privilege on. This
    form of <command>REPACK</command> cannot be executed inside a transaction
-   block.
+   block.  Also, this form is not allowed if
+   the <literal>CONCURRENTLY</literal> option is used.
   </para>
 
   <para>
@@ -67,7 +69,8 @@ REPACK [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] USING
    When a table is being repacked, an <literal>ACCESS EXCLUSIVE</literal> lock
    is acquired on it. This prevents any other database operations (both reads
    and writes) from operating on the table until the <command>REPACK</command>
-   is finished.
+   is finished. If you want to keep the table accessible during the repacking,
+   consider using the <literal>CONCURRENTLY</literal> option.
   </para>
 
   <refsect2 id="sql-repack-notes-on-clustering" xreflabel="Notes on Clustering">
@@ -195,6 +198,128 @@ REPACK [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] USING
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>CONCURRENTLY</literal></term>
+    <listitem>
+     <para>
+      Allow other transactions to use the table while it is being repacked.
+     </para>
+
+     <para>
+      Internally, <command>REPACK</command> copies the contents of the table
+      (ignoring dead tuples) into a new file, sorted by the specified index,
+      and also creates a new file for each index. Then it swaps the old and
+      new files for the table and all the indexes, and deletes the old
+      files. The <literal>ACCESS EXCLUSIVE</literal> lock is needed to make
+      sure that the old files do not change during the processing because the
+      changes would get lost due to the swap.
+     </para>
+
+     <para>
+      With the <literal>CONCURRENTLY</literal> option, the <literal>ACCESS
+      EXCLUSIVE</literal> lock is only acquired to swap the table and index
+      files. The data changes that took place during the creation of the new
+      table and index files are captured using logical decoding
+      (<xref linkend="logicaldecoding"/>) and applied before
+      the <literal>ACCESS EXCLUSIVE</literal> lock is requested. Thus the lock
+      is typically held only for the time needed to swap the files, which
+      should be pretty short. However, the time might still be noticeable if
+      too many data changes have been done to the table while
+      <command>REPACK</command> was waiting for the lock: those changes must
+      be processed just before the files are swapped, while the
+      <literal>ACCESS EXCLUSIVE</literal> lock is being held.
+     </para>
+
+     <para>
+      Note that <command>REPACK</command> with the
+      the <literal>CONCURRENTLY</literal> option does not try to order the
+      rows inserted into the table after the repacking started. Also
+      note <command>REPACK</command> might fail to complete due to DDL
+      commands executed on the table by other transactions during the
+      repacking.
+     </para>
+
+     <note>
+      <para>
+       In addition to the temporary space requirements explained in
+       <xref linkend="sql-repack-notes-on-resources"/>,
+       the <literal>CONCURRENTLY</literal> option can add to the usage of
+       temporary space a bit more. The reason is that other transactions can
+       perform DML operations which cannot be applied to the new file until
+       <command>REPACK</command> has copied all the tuples from the old
+       file. Thus the tuples inserted into the old file during the copying are
+       also stored separately in a temporary file, so they can eventually be
+       applied to the new file.
+      </para>
+
+      <para>
+       Furthermore, the data changes performed during the copying are
+       extracted from <link linkend="wal">write-ahead log</link> (WAL), and
+       this extraction (decoding) only takes place when certain amount of WAL
+       has been written. Therefore, WAL removal can be delayed by this
+       threshold. Currently the threshold is equal to the value of
+       the <link linkend="guc-wal-segment-size"><varname>wal_segment_size</varname></link>
+       configuration parameter.
+      </para>
+     </note>
+
+     <para>
+      The <literal>CONCURRENTLY</literal> option cannot be used in the
+      following cases:
+
+      <itemizedlist>
+       <listitem>
+        <para>
+          The table is <literal>UNLOGGED</literal>.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+          The table is partitioned.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+          The table is a system catalog or a <acronym>TOAST</acronym> table.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         <command>REPACK</command> is executed inside a transaction block.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+          The <link linkend="guc-wal-level"><varname>wal_level</varname></link>
+          configuration parameter is less than <literal>logical</literal>.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         The <link linkend="guc-max-replication-slots"><varname>max_replication_slots</varname></link>
+         configuration parameter does not allow for creation of an additional
+         replication slot.
+        </para>
+       </listitem>
+      </itemizedlist>
+     </para>
+
+     <warning>
+      <para>
+       <command>REPACK</command> with the <literal>CONCURRENTLY</literal>
+       option is not MVCC-safe, see <xref linkend="mvcc-caveats"/> for
+       details.
+      </para>
+     </warning>
+
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>VERBOSE</literal></term>
     <listitem>
diff --git a/src/Makefile b/src/Makefile
index 2f31a2f20a7..b18c9a14ffa 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -23,6 +23,7 @@ SUBDIRS = \
 	interfaces \
 	backend/replication/libpqwalreceiver \
 	backend/replication/pgoutput \
+	backend/replication/pgoutput_repack \
 	fe_utils \
 	bin \
 	pl \
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4d382a04338..f019f93bca6 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -60,7 +60,8 @@ static HeapTuple heap_prepare_insert(Relation relation, HeapTuple tup,
 static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
 								  Buffer newbuf, HeapTuple oldtup,
 								  HeapTuple newtup, HeapTuple old_key_tuple,
-								  bool all_visible_cleared, bool new_all_visible_cleared);
+								  bool all_visible_cleared, bool new_all_visible_cleared,
+								  bool wal_logical);
 #ifdef USE_ASSERT_CHECKING
 static void check_lock_if_inplace_updateable_rel(Relation relation,
 												 const ItemPointerData *otid,
@@ -2803,7 +2804,7 @@ xmax_infomask_changed(uint16 new_infomask, uint16 old_infomask)
 TM_Result
 heap_delete(Relation relation, const ItemPointerData *tid,
 			CommandId cid, Snapshot crosscheck, bool wait,
-			TM_FailureData *tmfd, bool changingPart)
+			TM_FailureData *tmfd, bool changingPart, bool wal_logical)
 {
 	TM_Result	result;
 	TransactionId xid = GetCurrentTransactionId();
@@ -3050,7 +3051,8 @@ l1:
 	 * Compute replica identity tuple before entering the critical section so
 	 * we don't PANIC upon a memory allocation failure.
 	 */
-	old_key_tuple = ExtractReplicaIdentity(relation, &tp, true, &old_key_copied);
+	old_key_tuple = wal_logical ?
+		ExtractReplicaIdentity(relation, &tp, true, &old_key_copied) : NULL;
 
 	/*
 	 * If this is the first possibly-multixact-able operation in the current
@@ -3140,6 +3142,15 @@ l1:
 				xlrec.flags |= XLH_DELETE_CONTAINS_OLD_KEY;
 		}
 
+		/*
+		 * Unlike UPDATE, DELETE is decoded even if there is no old key, so it
+		 * does not help to clear both XLH_DELETE_CONTAINS_OLD_TUPLE and
+		 * XLH_DELETE_CONTAINS_OLD_KEY. Thus we need an extra flag. TODO
+		 * Consider not decoding tuples w/o the old tuple/key instead.
+		 */
+		if (!wal_logical)
+			xlrec.flags |= XLH_DELETE_NO_LOGICAL;
+
 		XLogBeginInsert();
 		XLogRegisterData(&xlrec, SizeOfHeapDelete);
 
@@ -3232,7 +3243,8 @@ simple_heap_delete(Relation relation, const ItemPointerData *tid)
 	result = heap_delete(relation, tid,
 						 GetCurrentCommandId(true), InvalidSnapshot,
 						 true /* wait for commit */ ,
-						 &tmfd, false /* changingPart */ );
+						 &tmfd, false,	/* changingPart */
+						 true /* wal_logical */ );
 	switch (result)
 	{
 		case TM_SelfModified:
@@ -3273,7 +3285,7 @@ TM_Result
 heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup,
 			CommandId cid, Snapshot crosscheck, bool wait,
 			TM_FailureData *tmfd, LockTupleMode *lockmode,
-			TU_UpdateIndexes *update_indexes)
+			TU_UpdateIndexes *update_indexes, bool wal_logical)
 {
 	TM_Result	result;
 	TransactionId xid = GetCurrentTransactionId();
@@ -4166,7 +4178,8 @@ l2:
 								 newbuf, &oldtup, heaptup,
 								 old_key_tuple,
 								 all_visible_cleared,
-								 all_visible_cleared_new);
+								 all_visible_cleared_new,
+								 wal_logical);
 		if (newbuf != buffer)
 		{
 			PageSetLSN(BufferGetPage(newbuf), recptr);
@@ -4524,7 +4537,8 @@ simple_heap_update(Relation relation, const ItemPointerData *otid, HeapTuple tup
 	result = heap_update(relation, otid, tup,
 						 GetCurrentCommandId(true), InvalidSnapshot,
 						 true /* wait for commit */ ,
-						 &tmfd, &lockmode, update_indexes);
+						 &tmfd, &lockmode, update_indexes,
+						 true /* wal_logical */ );
 	switch (result)
 	{
 		case TM_SelfModified:
@@ -8864,7 +8878,8 @@ static XLogRecPtr
 log_heap_update(Relation reln, Buffer oldbuf,
 				Buffer newbuf, HeapTuple oldtup, HeapTuple newtup,
 				HeapTuple old_key_tuple,
-				bool all_visible_cleared, bool new_all_visible_cleared)
+				bool all_visible_cleared, bool new_all_visible_cleared,
+				bool wal_logical)
 {
 	xl_heap_update xlrec;
 	xl_heap_header xlhdr;
@@ -8875,7 +8890,8 @@ log_heap_update(Relation reln, Buffer oldbuf,
 				suffixlen = 0;
 	XLogRecPtr	recptr;
 	Page		page = BufferGetPage(newbuf);
-	bool		need_tuple_data = RelationIsLogicallyLogged(reln);
+	bool		need_tuple_data = RelationIsLogicallyLogged(reln) &&
+		wal_logical;
 	bool		init;
 	int			bufflags;
 
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 79f9de5d760..01be29eb405 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -33,6 +33,7 @@
 #include "catalog/index.h"
 #include "catalog/storage.h"
 #include "catalog/storage_xlog.h"
+#include "commands/cluster.h"
 #include "commands/progress.h"
 #include "executor/executor.h"
 #include "miscadmin.h"
@@ -309,7 +310,8 @@ heapam_tuple_delete(Relation relation, ItemPointer tid, CommandId cid,
 	 * the storage itself is cleaning the dead tuples by itself, it is the
 	 * time to call the index tuple deletion also.
 	 */
-	return heap_delete(relation, tid, cid, crosscheck, wait, tmfd, changingPart);
+	return heap_delete(relation, tid, cid, crosscheck, wait, tmfd, changingPart,
+					   true);
 }
 
 
@@ -328,7 +330,7 @@ heapam_tuple_update(Relation relation, ItemPointer otid, TupleTableSlot *slot,
 	tuple->t_tableOid = slot->tts_tableOid;
 
 	result = heap_update(relation, otid, tuple, cid, crosscheck, wait,
-						 tmfd, lockmode, update_indexes);
+						 tmfd, lockmode, update_indexes, true);
 	ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
 
 	/*
@@ -685,13 +687,15 @@ static void
 heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 								 Relation OldIndex, bool use_sort,
 								 TransactionId OldestXmin,
+								 Snapshot snapshot,
+								 LogicalDecodingContext *decoding_ctx,
 								 TransactionId *xid_cutoff,
 								 MultiXactId *multi_cutoff,
 								 double *num_tuples,
 								 double *tups_vacuumed,
 								 double *tups_recently_dead)
 {
-	RewriteState rwstate;
+	RewriteState rwstate = NULL;
 	IndexScanDesc indexScan;
 	TableScanDesc tableScan;
 	HeapScanDesc heapScan;
@@ -705,6 +709,8 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 	bool	   *isnull;
 	BufferHeapTupleTableSlot *hslot;
 	BlockNumber prev_cblock = InvalidBlockNumber;
+	bool		concurrent = snapshot != NULL;
+	XLogRecPtr	end_of_wal_prev = GetFlushRecPtr(NULL);
 
 	/* Remember if it's a system catalog */
 	is_system_catalog = IsSystemRelation(OldHeap);
@@ -720,9 +726,12 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 	values = (Datum *) palloc(natts * sizeof(Datum));
 	isnull = (bool *) palloc(natts * sizeof(bool));
 
-	/* Initialize the rewrite operation */
-	rwstate = begin_heap_rewrite(OldHeap, NewHeap, OldestXmin, *xid_cutoff,
-								 *multi_cutoff);
+	/*
+	 * Initialize the rewrite operation.
+	 */
+	if (!concurrent)
+		rwstate = begin_heap_rewrite(OldHeap, NewHeap, OldestXmin,
+									 *xid_cutoff, *multi_cutoff);
 
 
 	/* Set up sorting if wanted */
@@ -737,6 +746,9 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 	 * Prepare to scan the OldHeap.  To ensure we see recently-dead tuples
 	 * that still need to be copied, we scan with SnapshotAny and use
 	 * HeapTupleSatisfiesVacuum for the visibility test.
+	 *
+	 * In the CONCURRENTLY case, we do regular MVCC visibility tests, using
+	 * the snapshot passed by the caller.
 	 */
 	if (OldIndex != NULL && !use_sort)
 	{
@@ -753,7 +765,9 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 
 		tableScan = NULL;
 		heapScan = NULL;
-		indexScan = index_beginscan(OldHeap, OldIndex, SnapshotAny, NULL, 0, 0);
+		indexScan = index_beginscan(OldHeap, OldIndex,
+									snapshot ? snapshot : SnapshotAny,
+									NULL, 0, 0);
 		index_rescan(indexScan, NULL, 0, NULL, 0);
 	}
 	else
@@ -762,7 +776,9 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 		pgstat_progress_update_param(PROGRESS_REPACK_PHASE,
 									 PROGRESS_REPACK_PHASE_SEQ_SCAN_HEAP);
 
-		tableScan = table_beginscan(OldHeap, SnapshotAny, 0, (ScanKey) NULL);
+		tableScan = table_beginscan(OldHeap,
+									snapshot ? snapshot : SnapshotAny,
+									0, (ScanKey) NULL);
 		heapScan = (HeapScanDesc) tableScan;
 		indexScan = NULL;
 
@@ -837,70 +853,77 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 		tuple = ExecFetchSlotHeapTuple(slot, false, NULL);
 		buf = hslot->buffer;
 
-		LockBuffer(buf, BUFFER_LOCK_SHARE);
-
-		switch (HeapTupleSatisfiesVacuum(tuple, OldestXmin, buf))
+		/*
+		 * Regarding CONCURRENTLY, see the comments on MVCC snapshot above.
+		 */
+		if (!concurrent)
 		{
-			case HEAPTUPLE_DEAD:
-				/* Definitely dead */
-				isdead = true;
-				break;
-			case HEAPTUPLE_RECENTLY_DEAD:
-				*tups_recently_dead += 1;
-				/* fall through */
-			case HEAPTUPLE_LIVE:
-				/* Live or recently dead, must copy it */
-				isdead = false;
-				break;
-			case HEAPTUPLE_INSERT_IN_PROGRESS:
+			LockBuffer(buf, BUFFER_LOCK_SHARE);
 
-				/*
-				 * Since we hold exclusive lock on the relation, normally the
-				 * only way to see this is if it was inserted earlier in our
-				 * own transaction.  However, it can happen in system
-				 * catalogs, since we tend to release write lock before commit
-				 * there.  Give a warning if neither case applies; but in any
-				 * case we had better copy it.
-				 */
-				if (!is_system_catalog &&
-					!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple->t_data)))
-					elog(WARNING, "concurrent insert in progress within table \"%s\"",
-						 RelationGetRelationName(OldHeap));
-				/* treat as live */
-				isdead = false;
-				break;
-			case HEAPTUPLE_DELETE_IN_PROGRESS:
+			switch (HeapTupleSatisfiesVacuum(tuple, OldestXmin, buf))
+			{
+				case HEAPTUPLE_DEAD:
+					/* Definitely dead */
+					isdead = true;
+					break;
+				case HEAPTUPLE_RECENTLY_DEAD:
+					*tups_recently_dead += 1;
+					/* fall through */
+				case HEAPTUPLE_LIVE:
+					/* Live or recently dead, must copy it */
+					isdead = false;
+					break;
+				case HEAPTUPLE_INSERT_IN_PROGRESS:
 
-				/*
-				 * Similar situation to INSERT_IN_PROGRESS case.
-				 */
-				if (!is_system_catalog &&
-					!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetUpdateXid(tuple->t_data)))
-					elog(WARNING, "concurrent delete in progress within table \"%s\"",
-						 RelationGetRelationName(OldHeap));
-				/* treat as recently dead */
-				*tups_recently_dead += 1;
-				isdead = false;
-				break;
-			default:
-				elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
-				isdead = false; /* keep compiler quiet */
-				break;
-		}
+					/*
+					 * As long as we hold exclusive lock on the relation,
+					 * normally the only way to see this is if it was inserted
+					 * earlier in our own transaction.  However, it can happen
+					 * in system catalogs, since we tend to release write lock
+					 * before commit there. Give a warning if neither case
+					 * applies; but in any case we had better copy it.
+					 */
+					if (!is_system_catalog &&
+						!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple->t_data)))
+						elog(WARNING, "concurrent insert in progress within table \"%s\"",
+							 RelationGetRelationName(OldHeap));
+					/* treat as live */
+					isdead = false;
+					break;
+				case HEAPTUPLE_DELETE_IN_PROGRESS:
+
+					/*
+					 * Similar situation to INSERT_IN_PROGRESS case.
+					 */
+					if (!is_system_catalog &&
+						!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetUpdateXid(tuple->t_data)))
+						elog(WARNING, "concurrent delete in progress within table \"%s\"",
+							 RelationGetRelationName(OldHeap));
+					/* treat as recently dead */
+					*tups_recently_dead += 1;
+					isdead = false;
+					break;
+				default:
+					elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
+					isdead = false; /* keep compiler quiet */
+					break;
+			}
 
-		LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+			LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 
-		if (isdead)
-		{
-			*tups_vacuumed += 1;
-			/* heap rewrite module still needs to see it... */
-			if (rewrite_heap_dead_tuple(rwstate, tuple))
+			if (isdead)
 			{
-				/* A previous recently-dead tuple is now known dead */
 				*tups_vacuumed += 1;
-				*tups_recently_dead -= 1;
+				/* heap rewrite module still needs to see it... */
+				if (rewrite_heap_dead_tuple(rwstate, tuple))
+				{
+					/* A previous recently-dead tuple is now known dead */
+					*tups_vacuumed += 1;
+					*tups_recently_dead -= 1;
+				}
+
+				continue;
 			}
-			continue;
 		}
 
 		*num_tuples += 1;
@@ -919,7 +942,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 		{
 			const int	ct_index[] = {
 				PROGRESS_REPACK_HEAP_TUPLES_SCANNED,
-				PROGRESS_REPACK_HEAP_TUPLES_WRITTEN
+				PROGRESS_REPACK_HEAP_TUPLES_INSERTED
 			};
 			int64		ct_val[2];
 
@@ -934,6 +957,31 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 			ct_val[1] = *num_tuples;
 			pgstat_progress_update_multi_param(2, ct_index, ct_val);
 		}
+
+		/*
+		 * Process the WAL produced by the load, as well as by other
+		 * transactions, so that the replication slot can advance and WAL does
+		 * not pile up. Use wal_segment_size as a threshold so that we do not
+		 * introduce the decoding overhead too often.
+		 *
+		 * Of course, we must not apply the changes until the initial load has
+		 * completed.
+		 *
+		 * Note that our insertions into the new table should not be decoded
+		 * as we (intentionally) do not write the logical decoding specific
+		 * information to WAL.
+		 */
+		if (concurrent)
+		{
+			XLogRecPtr	end_of_wal;
+
+			end_of_wal = GetFlushRecPtr(NULL);
+			if ((end_of_wal - end_of_wal_prev) > wal_segment_size)
+			{
+				repack_decode_concurrent_changes(decoding_ctx, end_of_wal);
+				end_of_wal_prev = end_of_wal;
+			}
+		}
 	}
 
 	if (indexScan != NULL)
@@ -977,15 +1025,32 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 									 values, isnull,
 									 rwstate);
 			/* Report n_tuples */
-			pgstat_progress_update_param(PROGRESS_REPACK_HEAP_TUPLES_WRITTEN,
+			pgstat_progress_update_param(PROGRESS_REPACK_HEAP_TUPLES_INSERTED,
 										 n_tuples);
+
+			/*
+			 * Try to keep the amount of not-yet-decoded WAL small, like
+			 * above.
+			 */
+			if (concurrent)
+			{
+				XLogRecPtr	end_of_wal;
+
+				end_of_wal = GetFlushRecPtr(NULL);
+				if ((end_of_wal - end_of_wal_prev) > wal_segment_size)
+				{
+					repack_decode_concurrent_changes(decoding_ctx, end_of_wal);
+					end_of_wal_prev = end_of_wal;
+				}
+			}
 		}
 
 		tuplesort_end(tuplesort);
 	}
 
 	/* Write out any remaining tuples, and fsync if needed */
-	end_heap_rewrite(rwstate);
+	if (rwstate)
+		end_heap_rewrite(rwstate);
 
 	/* Clean up */
 	pfree(values);
@@ -2376,6 +2441,10 @@ heapam_scan_sample_next_tuple(TableScanDesc scan, SampleScanState *scanstate,
  * SET WITHOUT OIDS.
  *
  * So, we must reconstruct the tuple from component Datums.
+ *
+ * If rwstate=NULL, use simple_heap_insert() instead of rewriting - in that
+ * case we still need to deform/form the tuple. TODO Shouldn't we rename the
+ * function, as might not do any rewrite?
  */
 static void
 reform_and_rewrite_tuple(HeapTuple tuple,
@@ -2398,8 +2467,28 @@ reform_and_rewrite_tuple(HeapTuple tuple,
 
 	copiedTuple = heap_form_tuple(newTupDesc, values, isnull);
 
-	/* The heap rewrite module does the rest */
-	rewrite_heap_tuple(rwstate, tuple, copiedTuple);
+	if (rwstate)
+		/* The heap rewrite module does the rest */
+		rewrite_heap_tuple(rwstate, tuple, copiedTuple);
+	else
+	{
+		/*
+		 * Insert tuple when processing REPACK CONCURRENTLY.
+		 *
+		 * rewriteheap.c is not used in the CONCURRENTLY case because it'd be
+		 * difficult to do the same in the catch-up phase (as the logical
+		 * decoding does not provide us with sufficient visibility
+		 * information). Thus we must use heap_insert() both during the
+		 * catch-up and here.
+		 *
+		 * The following is like simple_heap_insert() except that we pass the
+		 * flag to skip logical decoding: as soon as REPACK CONCURRENTLY swaps
+		 * the relation files, it drops this relation, so no logical
+		 * replication subscription should need the data.
+		 */
+		heap_insert(NewHeap, copiedTuple, GetCurrentCommandId(true),
+					HEAP_INSERT_NO_LOGICAL, NULL);
+	}
 
 	heap_freetuple(copiedTuple);
 }
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 66ab48f0fe0..ee83a0fc91d 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -617,9 +617,9 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
 		int			options = HEAP_INSERT_SKIP_FSM;
 
 		/*
-		 * While rewriting the heap for VACUUM FULL / CLUSTER, make sure data
-		 * for the TOAST table are not logically decoded.  The main heap is
-		 * WAL-logged as XLOG FPI records, which are not logically decoded.
+		 * While rewriting the heap for REPACK, make sure data for the TOAST
+		 * table are not logically decoded.  The main heap is WAL-logged as
+		 * XLOG FPI records, which are not logically decoded.
 		 */
 		options |= HEAP_INSERT_NO_LOGICAL;
 
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 092e197eba3..edf467a9125 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -216,6 +216,7 @@ typedef struct TransactionStateData
 	bool		parallelChildXact;	/* is any parent transaction parallel? */
 	bool		chain;			/* start a new block after this one */
 	bool		topXidLogged;	/* for a subxact: is top-level XID logged? */
+	bool		internal;		/* for a subxact: launched internally? */
 	struct TransactionStateData *parent;	/* back link to parent */
 } TransactionStateData;
 
@@ -4741,6 +4742,7 @@ BeginInternalSubTransaction(const char *name)
 			/* Normal subtransaction start */
 			PushTransaction();
 			s = CurrentTransactionState;	/* changed by push */
+			s->internal = true;
 
 			/*
 			 * Savepoint names, like the TransactionState block itself, live
@@ -5257,7 +5259,13 @@ AbortSubTransaction(void)
 	LWLockReleaseAll();
 
 	pgstat_report_wait_end();
-	pgstat_progress_end_command();
+
+	/*
+	 * Internal subtransacion might be used by an user command, in which case
+	 * the command outlives the subtransaction.
+	 */
+	if (!s->internal)
+		pgstat_progress_end_command();
 
 	pgaio_error_cleanup();
 
@@ -5474,6 +5482,7 @@ PushTransaction(void)
 	s->parallelModeLevel = 0;
 	s->parallelChildXact = (p->parallelModeLevel != 0 || p->parallelChildXact);
 	s->topXidLogged = false;
+	s->internal = false;
 
 	CurrentTransactionState = s;
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 024d219016d..941cd46ef67 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1287,16 +1287,19 @@ CREATE VIEW pg_stat_progress_repack AS
                       WHEN 2 THEN 'index scanning heap'
                       WHEN 3 THEN 'sorting tuples'
                       WHEN 4 THEN 'writing new heap'
-                      WHEN 5 THEN 'swapping relation files'
-                      WHEN 6 THEN 'rebuilding index'
-                      WHEN 7 THEN 'performing final cleanup'
+                      WHEN 5 THEN 'catch-up'
+                      WHEN 6 THEN 'swapping relation files'
+                      WHEN 7 THEN 'rebuilding index'
+                      WHEN 8 THEN 'performing final cleanup'
                       END AS phase,
         CAST(S.param3 AS oid) AS repack_index_relid,
         S.param4 AS heap_tuples_scanned,
-        S.param5 AS heap_tuples_written,
-        S.param6 AS heap_blks_total,
-        S.param7 AS heap_blks_scanned,
-        S.param8 AS index_rebuild_count
+        S.param5 AS heap_tuples_inserted,
+        S.param6 AS heap_tuples_updated,
+        S.param7 AS heap_tuples_deleted,
+        S.param8 AS heap_blks_total,
+        S.param9 AS heap_blks_scanned,
+        S.param10 AS index_rebuild_count
     FROM pg_stat_get_progress_info('REPACK') AS S
         LEFT JOIN pg_database D ON S.datid = D.oid;
 
@@ -1314,7 +1317,7 @@ CREATE VIEW pg_stat_progress_cluster AS
         phase,
         repack_index_relid AS cluster_index_relid,
         heap_tuples_scanned,
-        heap_tuples_written,
+        heap_tuples_inserted + heap_tuples_updated AS heap_tuples_written,
         heap_blks_total,
         heap_blks_scanned,
         index_rebuild_count
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index ba3c076ea7d..260d7cc07e0 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -26,6 +26,10 @@
 #include "access/toast_internals.h"
 #include "access/transam.h"
 #include "access/xact.h"
+#include "access/xlog.h"
+#include "access/xlog_internal.h"
+#include "access/xloginsert.h"
+#include "access/xlogutils.h"
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/heap.h"
@@ -33,6 +37,7 @@
 #include "catalog/namespace.h"
 #include "catalog/objectaccess.h"
 #include "catalog/pg_am.h"
+#include "catalog/pg_control.h"
 #include "catalog/pg_inherits.h"
 #include "catalog/toasting.h"
 #include "commands/cluster.h"
@@ -40,15 +45,21 @@
 #include "commands/progress.h"
 #include "commands/tablecmds.h"
 #include "commands/vacuum.h"
+#include "executor/executor.h"
 #include "miscadmin.h"
 #include "optimizer/optimizer.h"
 #include "pgstat.h"
+#include "replication/decode.h"
+#include "replication/logical.h"
+#include "replication/snapbuild.h"
 #include "storage/bufmgr.h"
+#include "storage/ipc.h"
 #include "storage/lmgr.h"
 #include "storage/predicate.h"
 #include "utils/acl.h"
 #include "utils/fmgroids.h"
 #include "utils/guc.h"
+#include "utils/injection_point.h"
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
@@ -68,13 +79,68 @@ typedef struct
 	Oid			indexOid;
 } RelToCluster;
 
+/*
+ * The following definitions are used for concurrent processing.
+ */
+
+/*
+ * The locators are used to avoid logical decoding of data that we do not need
+ * for our table.
+ */
+RelFileLocator repacked_rel_locator = {.relNumber = InvalidOid};
+RelFileLocator repacked_rel_toast_locator = {.relNumber = InvalidOid};
+
+/*
+ * Everything we need to call ExecInsertIndexTuples().
+ */
+typedef struct IndexInsertState
+{
+	ResultRelInfo *rri;
+	EState	   *estate;
+} IndexInsertState;
+
+/* The WAL segment being decoded. */
+static XLogSegNo repack_current_segment = 0;
+
+/*
+ * Information needed to apply concurrent data changes.
+ */
+typedef struct ChangeDest
+{
+	/* The relation the changes are applied to. */
+	Relation	rel;
+
+	/*
+	 * If valid, set rel->rd_toastoid to this for the time the changes are
+	 * being applied.
+	 */
+	Oid			toastrelid;
+
+	/*
+	 * The following is needed to find the existing tuple if the change is
+	 * UPDATE or DELETE. 'ident_key' should have all the fields except for
+	 * 'sk_argument' initialized.
+	 */
+	Relation	ident_index;
+	ScanKey		ident_key;
+	int			ident_key_nentries;
+
+	/* Needed to update indexes of rel_dst. */
+	IndexInsertState *iistate;
+} ChangeDest;
+
 static bool cluster_rel_recheck(RepackCommand cmd, Relation OldHeap,
-								Oid indexOid, Oid userid, int options);
-static void rebuild_relation(RepackCommand cmd,
-							 Relation OldHeap, Relation index, bool verbose);
+								Oid indexOid, Oid userid, LOCKMODE lmode,
+								int options);
+static void check_repack_concurrently_requirements(Relation rel);
+static void rebuild_relation(RepackCommand cmd, Relation OldHeap, Relation index,
+							 bool verbose, bool concurrently);
 static void copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex,
-							bool verbose, bool *pSwapToastByContent,
-							TransactionId *pFreezeXid, MultiXactId *pCutoffMulti);
+							Snapshot snapshot, LogicalDecodingContext *decoding_ctx,
+							bool verbose,
+							bool *pSwapToastByContent,
+							TransactionId *pFreezeXid,
+							MultiXactId *pCutoffMulti);
 static List *get_tables_to_repack(RepackCommand cmd, bool usingindex,
 								  MemoryContext permcxt);
 static List *get_tables_to_repack_partitioned(RepackCommand cmd,
@@ -82,13 +148,54 @@ static List *get_tables_to_repack_partitioned(RepackCommand cmd,
 											  MemoryContext permcxt);
 static bool cluster_is_permitted_for_relation(RepackCommand cmd,
 											  Oid relid, Oid userid);
+
+static void begin_concurrent_repack(Relation rel);
+static void end_concurrent_repack(void);
+static LogicalDecodingContext *setup_logical_decoding(Oid relid);
+static HeapTuple get_changed_tuple(char *change);
+static void apply_concurrent_changes(RepackDecodingState *dstate,
+									 ChangeDest *dest);
+static void apply_concurrent_insert(Relation rel, ConcurrentChange *change,
+									HeapTuple tup, IndexInsertState *iistate,
+									TupleTableSlot *index_slot);
+static void apply_concurrent_update(Relation rel, HeapTuple tup,
+									HeapTuple tup_target,
+									ConcurrentChange *change,
+									IndexInsertState *iistate,
+									TupleTableSlot *index_slot);
+static void apply_concurrent_delete(Relation rel, HeapTuple tup_target,
+									ConcurrentChange *change);
+static HeapTuple find_target_tuple(Relation rel, ChangeDest *dest,
+								   HeapTuple tup_key,
+								   TupleTableSlot *ident_slot);
+static void process_concurrent_changes(LogicalDecodingContext *decoding_ctx,
+									   XLogRecPtr end_of_wal,
+									   ChangeDest *dest);
+static IndexInsertState *get_index_insert_state(Relation relation,
+												Oid ident_index_id,
+												Relation *ident_index_p);
+static ScanKey build_identity_key(Oid ident_idx_oid, Relation rel_src,
+								  int *nentries);
+static void free_index_insert_state(IndexInsertState *iistate);
+static void cleanup_logical_decoding(LogicalDecodingContext *ctx);
+static void rebuild_relation_finish_concurrent(Relation NewHeap, Relation OldHeap,
+											   Relation cl_index,
+											   LogicalDecodingContext *decoding_ctx,
+											   bool swap_toast_by_content,
+											   TransactionId frozenXid,
+											   MultiXactId cutoffMulti);
+static List *build_new_indexes(Relation NewHeap, Relation OldHeap, List *OldIndexes);
 static Relation process_single_relation(RepackStmt *stmt,
+										LOCKMODE lockmode,
+										bool isTopLevel,
 										ClusterParams *params);
 static Oid	determine_clustered_index(Relation rel, bool usingindex,
 									  const char *indexname);
 static const char *RepackCommandAsString(RepackCommand cmd);
 
 
+#define REPL_PLUGIN_NAME   "pgoutput_repack"
+
 /*
  * The repack code allows for processing multiple tables at once. Because
  * of this, we cannot just run everything on a single transaction, or we
@@ -118,6 +225,7 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 	ClusterParams params = {0};
 	Relation	rel = NULL;
 	MemoryContext repack_context;
+	LOCKMODE	lockmode;
 	List	   *rtcs;
 
 	/* Parse option list */
@@ -128,6 +236,16 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 		else if (strcmp(opt->defname, "analyze") == 0 ||
 				 strcmp(opt->defname, "analyse") == 0)
 			params.options |= defGetBoolean(opt) ? CLUOPT_ANALYZE : 0;
+		else if (strcmp(opt->defname, "concurrently") == 0 &&
+				 defGetBoolean(opt))
+		{
+			if (stmt->command != REPACK_COMMAND_REPACK)
+				ereport(ERROR,
+						errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						errmsg("CONCURRENTLY option not supported for %s",
+							   RepackCommandAsString(stmt->command)));
+			params.options |= CLUOPT_CONCURRENT;
+		}
 		else
 			ereport(ERROR,
 					errcode(ERRCODE_SYNTAX_ERROR),
@@ -137,13 +255,25 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 					parser_errposition(pstate, opt->location));
 	}
 
+	/*
+	 * Determine the lock mode expected by cluster_rel().
+	 *
+	 * In the exclusive case, we obtain AccessExclusiveLock right away to
+	 * avoid lock-upgrade hazard in the single-transaction case. In the
+	 * CONCURRENTLY case, the AccessExclusiveLock will only be used at the end
+	 * of processing, supposedly for very short time. Until then, we'll have
+	 * to unlock the relation temporarily, so there's no lock-upgrade hazard.
+	 */
+	lockmode = (params.options & CLUOPT_CONCURRENT) == 0 ?
+		AccessExclusiveLock : ShareUpdateExclusiveLock;
+
 	/*
 	 * If a single relation is specified, process it and we're done ... unless
 	 * the relation is a partitioned table, in which case we fall through.
 	 */
 	if (stmt->relation != NULL)
 	{
-		rel = process_single_relation(stmt, &params);
+		rel = process_single_relation(stmt, lockmode, isTopLevel, &params);
 		if (rel == NULL)
 			return;				/* all done */
 	}
@@ -158,10 +288,29 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 				errmsg("cannot %s multiple tables", "REPACK (ANALYZE)"));
 
 	/*
-	 * By here, we know we are in a multi-table situation.  In order to avoid
-	 * holding locks for too long, we want to process each table in its own
-	 * transaction.  This forces us to disallow running inside a user
-	 * transaction block.
+	 * By here, we know we are in a multi-table situation.
+	 *
+	 * Concurrent processing is currently considered rather special (e.g. in
+	 * terms of resources consumed) so it is not performed in bulk.
+	 */
+	if (params.options & CLUOPT_CONCURRENT)
+	{
+		if (rel != NULL)
+		{
+			Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
+			ereport(ERROR,
+					errmsg("REPACK CONCURRENTLY not supported for partitioned tables"),
+					errhint("Consider running the command for individual partitions."));
+		}
+		else
+			ereport(ERROR,
+					errmsg("REPACK CONCURRENTLY requires explicit table name"));
+	}
+
+	/*
+	 * In order to avoid holding locks for too long, we want to process each
+	 * table in its own transaction.  This forces us to disallow running
+	 * inside a user transaction block.
 	 */
 	PreventInTransactionBlock(isTopLevel, RepackCommandAsString(stmt->command));
 
@@ -244,7 +393,7 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 		 * Open the target table, coping with the case where it has been
 		 * dropped.
 		 */
-		rel = try_table_open(rtc->tableOid, AccessExclusiveLock);
+		rel = try_table_open(rtc->tableOid, lockmode);
 		if (rel == NULL)
 		{
 			CommitTransactionCommand();
@@ -255,7 +404,7 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 		PushActiveSnapshot(GetTransactionSnapshot());
 
 		/* Process this table */
-		cluster_rel(stmt->command, rel, rtc->indexOid, &params);
+		cluster_rel(stmt->command, rel, rtc->indexOid, &params, isTopLevel);
 		/* cluster_rel closes the relation, but keeps lock */
 
 		PopActiveSnapshot();
@@ -284,22 +433,53 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
  * If indexOid is InvalidOid, the table will be rewritten in physical order
  * instead of index order.
  *
+ * Note that, in the concurrent case, the function releases the lock at some
+ * point, in order to get AccessExclusiveLock for the final steps (i.e. to
+ * swap the relation files). To make things simpler, the caller should expect
+ * OldHeap to be closed on return, regardless CLUOPT_CONCURRENT. (The
+ * AccessExclusiveLock is kept till the end of the transaction.)
+ *
  * 'cmd' indicates which command is being executed, to be used for error
  * messages.
  */
 void
 cluster_rel(RepackCommand cmd, Relation OldHeap, Oid indexOid,
-			ClusterParams *params)
+			ClusterParams *params, bool isTopLevel)
 {
 	Oid			tableOid = RelationGetRelid(OldHeap);
+	Relation	index;
+	LOCKMODE	lmode;
 	Oid			save_userid;
 	int			save_sec_context;
 	int			save_nestlevel;
 	bool		verbose = ((params->options & CLUOPT_VERBOSE) != 0);
 	bool		recheck = ((params->options & CLUOPT_RECHECK) != 0);
-	Relation	index;
+	bool		concurrent = ((params->options & CLUOPT_CONCURRENT) != 0);
+
+	/*
+	 * The lock mode is AccessExclusiveLock for normal processing and
+	 * ShareUpdateExclusiveLock for concurrent processing (so that SELECT,
+	 * INSERT, UPDATE and DELETE commands work, but cluster_rel() cannot be
+	 * called concurrently for the same relation).
+	 */
+	lmode = !concurrent ? AccessExclusiveLock : ShareUpdateExclusiveLock;
+
+	/* There are specific requirements on concurrent processing. */
+	if (concurrent)
+	{
+		/*
+		 * Make sure we have no XID assigned, otherwise call of
+		 * setup_logical_decoding() can cause a deadlock.
+		 *
+		 * The existence of transaction block actually does not imply that XID
+		 * was already assigned, but it very likely is. We might want to check
+		 * the result of GetCurrentTransactionIdIfAny() instead, but that
+		 * would be less clear from user's perspective.
+		 */
+		PreventInTransactionBlock(isTopLevel, "REPACK (CONCURRENTLY)");
 
-	Assert(CheckRelationLockedByMe(OldHeap, AccessExclusiveLock, false));
+		check_repack_concurrently_requirements(OldHeap);
+	}
 
 	/* Check for user-requested abort. */
 	CHECK_FOR_INTERRUPTS();
@@ -325,10 +505,13 @@ cluster_rel(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 	 * If this is a single-transaction CLUSTER, we can skip these tests. We
 	 * *must* skip the one on indisclustered since it would reject an attempt
 	 * to cluster a not-previously-clustered index.
+	 *
+	 * XXX move [some of] these comments to where the RECHECK flag is
+	 * determined?
 	 */
 	if (recheck &&
 		!cluster_rel_recheck(cmd, OldHeap, indexOid, save_userid,
-							 params->options))
+							 lmode, params->options))
 		goto out;
 
 	/*
@@ -343,6 +526,12 @@ cluster_rel(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 				errmsg("cannot run %s on a shared catalog",
 					   RepackCommandAsString(cmd)));
 
+	/*
+	 * The CONCURRENTLY case should have been rejected earlier because it does
+	 * not support system catalogs.
+	 */
+	Assert(!(OldHeap->rd_rel->relisshared && concurrent));
+
 	/*
 	 * Don't process temp tables of other backends ... their local buffer
 	 * manager is not going to cope.
@@ -363,7 +552,7 @@ cluster_rel(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 	if (OidIsValid(indexOid))
 	{
 		/* verify the index is good and lock it */
-		check_index_is_clusterable(OldHeap, indexOid, AccessExclusiveLock);
+		check_index_is_clusterable(OldHeap, indexOid, lmode);
 		/* also open it */
 		index = index_open(indexOid, NoLock);
 	}
@@ -398,7 +587,9 @@ cluster_rel(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 	if (OldHeap->rd_rel->relkind == RELKIND_MATVIEW &&
 		!RelationIsPopulated(OldHeap))
 	{
-		relation_close(OldHeap, AccessExclusiveLock);
+		if (index)
+			index_close(index, lmode);
+		relation_close(OldHeap, lmode);
 		goto out;
 	}
 
@@ -411,11 +602,35 @@ cluster_rel(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 	 * invalid, because we move tuples around.  Promote them to relation
 	 * locks.  Predicate locks on indexes will be promoted when they are
 	 * reindexed.
+	 *
+	 * During concurrent processing, the heap as well as its indexes stay in
+	 * operation, so we postpone this step until they are locked using
+	 * AccessExclusiveLock near the end of the processing.
 	 */
-	TransferPredicateLocksToHeapRelation(OldHeap);
+	if (!concurrent)
+		TransferPredicateLocksToHeapRelation(OldHeap);
 
 	/* rebuild_relation does all the dirty work */
-	rebuild_relation(cmd, OldHeap, index, verbose);
+	PG_TRY();
+	{
+		/*
+		 * For concurrent processing, make sure that our logical decoding
+		 * ignores data changes of other tables than the one we are
+		 * processing.
+		 */
+		if (concurrent)
+			begin_concurrent_repack(OldHeap);
+
+		rebuild_relation(cmd, OldHeap, index, /* save_userid, */
+						 verbose, concurrent);
+	}
+	PG_FINALLY();
+	{
+		if (concurrent)
+			end_concurrent_repack();
+	}
+	PG_END_TRY();
+
 	/* rebuild_relation closes OldHeap, and index if valid */
 
 out:
@@ -434,14 +649,14 @@ out:
  */
 static bool
 cluster_rel_recheck(RepackCommand cmd, Relation OldHeap, Oid indexOid,
-					Oid userid, int options)
+					Oid userid, LOCKMODE lmode, int options)
 {
 	Oid			tableOid = RelationGetRelid(OldHeap);
 
 	/* Check that the user still has privileges for the relation */
 	if (!cluster_is_permitted_for_relation(cmd, tableOid, userid))
 	{
-		relation_close(OldHeap, AccessExclusiveLock);
+		relation_close(OldHeap, lmode);
 		return false;
 	}
 
@@ -455,7 +670,7 @@ cluster_rel_recheck(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 	 */
 	if (RELATION_IS_OTHER_TEMP(OldHeap))
 	{
-		relation_close(OldHeap, AccessExclusiveLock);
+		relation_close(OldHeap, lmode);
 		return false;
 	}
 
@@ -466,7 +681,7 @@ cluster_rel_recheck(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 		 */
 		if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(indexOid)))
 		{
-			relation_close(OldHeap, AccessExclusiveLock);
+			relation_close(OldHeap, lmode);
 			return false;
 		}
 
@@ -477,7 +692,7 @@ cluster_rel_recheck(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 		if ((options & CLUOPT_RECHECK_ISCLUSTERED) != 0 &&
 			!get_index_isclustered(indexOid))
 		{
-			relation_close(OldHeap, AccessExclusiveLock);
+			relation_close(OldHeap, lmode);
 			return false;
 		}
 	}
@@ -489,7 +704,7 @@ cluster_rel_recheck(RepackCommand cmd, Relation OldHeap, Oid indexOid,
  * Verify that the specified heap and index are valid to cluster on
  *
  * Side effect: obtains lock on the index.  The caller may
- * in some cases already have AccessExclusiveLock on the table, but
+ * in some cases already have a lock of the same strength on the table, but
  * not in all cases so we can't rely on the table-level lock for
  * protection here.
  */
@@ -618,19 +833,88 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
 	table_close(pg_index, RowExclusiveLock);
 }
 
+/*
+ * Check if the CONCURRENTLY option is legal for the relation.
+ */
+static void
+check_repack_concurrently_requirements(Relation rel)
+{
+	char		relpersistence,
+				replident;
+	Oid			ident_idx;
+
+	/* Data changes in system relations are not logically decoded. */
+	if (IsCatalogRelation(rel))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("cannot repack relation \"%s\"",
+						RelationGetRelationName(rel)),
+				 errhint("REPACK CONCURRENTLY is not supported for catalog relations.")));
+
+	/*
+	 * reorderbuffer.c does not seem to handle processing of TOAST relation
+	 * alone.
+	 */
+	if (IsToastRelation(rel))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("cannot repack relation \"%s\"",
+						RelationGetRelationName(rel)),
+				 errhint("REPACK CONCURRENTLY is not supported for TOAST relations, unless the main relation is repacked too.")));
+
+	relpersistence = rel->rd_rel->relpersistence;
+	if (relpersistence != RELPERSISTENCE_PERMANENT)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("cannot repack relation \"%s\"",
+						RelationGetRelationName(rel)),
+				 errhint("REPACK CONCURRENTLY is only allowed for permanent relations.")));
+
+	/* With NOTHING, WAL does not contain the old tuple. */
+	replident = rel->rd_rel->relreplident;
+	if (replident == REPLICA_IDENTITY_NOTHING)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("cannot repack relation \"%s\"",
+						RelationGetRelationName(rel)),
+				 errhint("Relation \"%s\" has insufficient replication identity.",
+						 RelationGetRelationName(rel))));
+
+	/*
+	 * Identity index is not set if the replica identity is FULL, but PK might
+	 * exist in such a case.
+	 */
+	ident_idx = RelationGetReplicaIndex(rel);
+	if (!OidIsValid(ident_idx) && OidIsValid(rel->rd_pkindex))
+		ident_idx = rel->rd_pkindex;
+	if (!OidIsValid(ident_idx))
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("cannot process relation \"%s\"",
+						RelationGetRelationName(rel)),
+				 (errhint("Relation \"%s\" has no identity index.",
+						  RelationGetRelationName(rel)))));
+}
+
+
 /*
  * rebuild_relation: rebuild an existing relation in index or physical order
  *
- * OldHeap: table to rebuild.
+ * OldHeap: table to rebuild.  See cluster_rel() for comments on the required
+ * lock strength.
+ *
  * index: index to cluster by, or NULL to rewrite in physical order.
  *
- * On entry, heap and index (if one is given) must be open, and
- * AccessExclusiveLock held on them.
- * On exit, they are closed, but locks on them are not released.
+ * On entry, heap and index (if one is given) must be open, and the
+ * appropriate lock held on them -- AccessExclusiveLock for exclusive
+ * processing and ShareUpdateExclusiveLock for concurrent processing.
+ *
+ * On exit, they are closed, but still locked with AccessExclusiveLock.
+ * (The function handles the lock upgrade if 'concurrent' is true.)
  */
 static void
-rebuild_relation(RepackCommand cmd,
-				 Relation OldHeap, Relation index, bool verbose)
+rebuild_relation(RepackCommand cmd, Relation OldHeap, Relation index,
+				 bool verbose, bool concurrent)
 {
 	Oid			tableOid = RelationGetRelid(OldHeap);
 	Oid			accessMethod = OldHeap->rd_rel->relam;
@@ -638,13 +922,38 @@ rebuild_relation(RepackCommand cmd,
 	Oid			OIDNewHeap;
 	Relation	NewHeap;
 	char		relpersistence;
-	bool		is_system_catalog;
 	bool		swap_toast_by_content;
 	TransactionId frozenXid;
 	MultiXactId cutoffMulti;
+	LogicalDecodingContext *decoding_ctx = NULL;
+	Snapshot	snapshot = NULL;
+#if USE_ASSERT_CHECKING
+	LOCKMODE	lmode;
+
+	lmode = concurrent ? ShareUpdateExclusiveLock : AccessExclusiveLock;
+
+	Assert(CheckRelationLockedByMe(OldHeap, lmode, false));
+	Assert(index == NULL || CheckRelationLockedByMe(index, lmode, false));
+#endif
 
-	Assert(CheckRelationLockedByMe(OldHeap, AccessExclusiveLock, false) &&
-		   (index == NULL || CheckRelationLockedByMe(index, AccessExclusiveLock, false)));
+	if (concurrent)
+	{
+		/*
+		 * Prepare to capture the concurrent data changes.
+		 *
+		 * Note that this call waits for all transactions with XID already
+		 * assigned to finish. If some of those transactions is waiting for a
+		 * lock conflicting with ShareUpdateExclusiveLock on our table (e.g.
+		 * it runs CREATE INDEX), we can end up in a deadlock. Not sure this
+		 * risk is worth unlocking/locking the table (and its clustering
+		 * index) and checking again if its still eligible for REPACK
+		 * CONCURRENTLY.
+		 */
+		decoding_ctx = setup_logical_decoding(tableOid);
+
+		snapshot = SnapBuildInitialSnapshotForRepack(decoding_ctx->snapshot_builder);
+		PushActiveSnapshot(snapshot);
+	}
 
 	/* for CLUSTER or REPACK USING INDEX, mark the index as the one to use */
 	if (index != NULL)
@@ -652,7 +961,6 @@ rebuild_relation(RepackCommand cmd,
 
 	/* Remember info about rel before closing OldHeap */
 	relpersistence = OldHeap->rd_rel->relpersistence;
-	is_system_catalog = IsSystemRelation(OldHeap);
 
 	/*
 	 * Create the transient table that will receive the re-ordered data.
@@ -668,30 +976,65 @@ rebuild_relation(RepackCommand cmd,
 	NewHeap = table_open(OIDNewHeap, NoLock);
 
 	/* Copy the heap data into the new table in the desired order */
-	copy_table_data(NewHeap, OldHeap, index, verbose,
+	copy_table_data(NewHeap, OldHeap, index, snapshot, decoding_ctx, verbose,
 					&swap_toast_by_content, &frozenXid, &cutoffMulti);
 
+	/* The historic snapshot won't be needed anymore. */
+	if (snapshot)
+		PopActiveSnapshot();
 
-	/* Close relcache entries, but keep lock until transaction commit */
-	table_close(OldHeap, NoLock);
-	if (index)
-		index_close(index, NoLock);
+	if (concurrent)
+	{
+		/*
+		 * Push a snapshot that we will use to find old versions of rows when
+		 * processing concurrent UPDATE and DELETE commands. (That snapshot
+		 * should also be used by index expressions.)
+		 */
+		PushActiveSnapshot(GetTransactionSnapshot());
 
-	/*
-	 * Close the new relation so it can be dropped as soon as the storage is
-	 * swapped. The relation is not visible to others, so no need to unlock it
-	 * explicitly.
-	 */
-	table_close(NewHeap, NoLock);
+		/*
+		 * Make sure we can find the tuples just inserted when applying DML
+		 * commands on top of those.
+		 */
+		CommandCounterIncrement();
+		UpdateActiveSnapshotCommandId();
 
-	/*
-	 * Swap the physical files of the target and transient tables, then
-	 * rebuild the target's indexes and throw away the transient table.
-	 */
-	finish_heap_swap(tableOid, OIDNewHeap, is_system_catalog,
-					 swap_toast_by_content, false, true,
-					 frozenXid, cutoffMulti,
-					 relpersistence);
+		rebuild_relation_finish_concurrent(NewHeap, OldHeap, index,
+										   decoding_ctx, swap_toast_by_content,
+										   frozenXid, cutoffMulti);
+		PopActiveSnapshot();
+
+		pgstat_progress_update_param(PROGRESS_REPACK_PHASE,
+									 PROGRESS_REPACK_PHASE_FINAL_CLEANUP);
+
+		/* Done with decoding. */
+		cleanup_logical_decoding(decoding_ctx);
+	}
+	else
+	{
+		bool		is_system_catalog = IsSystemRelation(OldHeap);
+
+		/* Close relcache entries, but keep lock until transaction commit */
+		table_close(OldHeap, NoLock);
+		if (index)
+			index_close(index, NoLock);
+
+		/*
+		 * Close the new relation so it can be dropped as soon as the storage
+		 * is swapped. The relation is not visible to others, so no need to
+		 * unlock it explicitly.
+		 */
+		table_close(NewHeap, NoLock);
+
+		/*
+		 * Swap the physical files of the target and transient tables, then
+		 * rebuild the target's indexes and throw away the transient table.
+		 */
+		finish_heap_swap(tableOid, OIDNewHeap, is_system_catalog,
+						 swap_toast_by_content, false, true, true,
+						 frozenXid, cutoffMulti,
+						 relpersistence);
+	}
 }
 
 
@@ -826,15 +1169,19 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, Oid NewAccessMethod,
 /*
  * Do the physical copying of table data.
  *
+ * 'snapshot' and 'decoding_ctx': see table_relation_copy_for_cluster(). Pass
+ * iff concurrent processing is required.
+ *
  * There are three output parameters:
  * *pSwapToastByContent is set true if toast tables must be swapped by content.
  * *pFreezeXid receives the TransactionId used as freeze cutoff point.
  * *pCutoffMulti receives the MultiXactId used as a cutoff point.
  */
 static void
-copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verbose,
-				bool *pSwapToastByContent, TransactionId *pFreezeXid,
-				MultiXactId *pCutoffMulti)
+copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex,
+				Snapshot snapshot, LogicalDecodingContext *decoding_ctx,
+				bool verbose, bool *pSwapToastByContent,
+				TransactionId *pFreezeXid, MultiXactId *pCutoffMulti)
 {
 	Relation	relRelation;
 	HeapTuple	reltup;
@@ -852,6 +1199,8 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb
 	PGRUsage	ru0;
 	char	   *nspname;
 
+	bool		concurrent = snapshot != NULL;
+
 	pg_rusage_init(&ru0);
 
 	/* Store a copy of the namespace name for logging purposes */
@@ -954,8 +1303,48 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb
 	 * provided, else plain seqscan.
 	 */
 	if (OldIndex != NULL && OldIndex->rd_rel->relam == BTREE_AM_OID)
+	{
+		ResourceOwner oldowner = NULL;
+		ResourceOwner resowner = NULL;
+
+		/*
+		 * In the CONCURRENT case, use a dedicated resource owner so we don't
+		 * leave any additional locks behind us that we cannot release easily.
+		 */
+		if (concurrent)
+		{
+			Assert(CheckRelationLockedByMe(OldHeap, ShareUpdateExclusiveLock,
+										   false));
+			Assert(CheckRelationLockedByMe(OldIndex, ShareUpdateExclusiveLock,
+										   false));
+
+			resowner = ResourceOwnerCreate(CurrentResourceOwner,
+										   "plan_cluster_use_sort");
+			oldowner = CurrentResourceOwner;
+			CurrentResourceOwner = resowner;
+		}
+
 		use_sort = plan_cluster_use_sort(RelationGetRelid(OldHeap),
 										 RelationGetRelid(OldIndex));
+
+		if (concurrent)
+		{
+			CurrentResourceOwner = oldowner;
+
+			/*
+			 * We are primarily concerned about locks, but if the planner
+			 * happened to allocate any other resources, we should release
+			 * them too because we're going to delete the whole resowner.
+			 */
+			ResourceOwnerRelease(resowner, RESOURCE_RELEASE_BEFORE_LOCKS,
+								 false, false);
+			ResourceOwnerRelease(resowner, RESOURCE_RELEASE_LOCKS,
+								 false, false);
+			ResourceOwnerRelease(resowner, RESOURCE_RELEASE_AFTER_LOCKS,
+								 false, false);
+			ResourceOwnerDelete(resowner);
+		}
+	}
 	else
 		use_sort = false;
 
@@ -984,7 +1373,9 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb
 	 * values (e.g. because the AM doesn't use freezing).
 	 */
 	table_relation_copy_for_cluster(OldHeap, NewHeap, OldIndex, use_sort,
-									cutoffs.OldestXmin, &cutoffs.FreezeLimit,
+									cutoffs.OldestXmin, snapshot,
+									decoding_ctx,
+									&cutoffs.FreezeLimit,
 									&cutoffs.MultiXactCutoff,
 									&num_tuples, &tups_vacuumed,
 									&tups_recently_dead);
@@ -993,7 +1384,11 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb
 	*pFreezeXid = cutoffs.FreezeLimit;
 	*pCutoffMulti = cutoffs.MultiXactCutoff;
 
-	/* Reset rd_toastoid just to be tidy --- it shouldn't be looked at again */
+	/*
+	 * Reset rd_toastoid just to be tidy --- it shouldn't be looked at again.
+	 * In the CONCURRENTLY case, we need to set it again before applying the
+	 * concurrent changes.
+	 */
 	NewHeap->rd_toastoid = InvalidOid;
 
 	num_pages = RelationGetNumberOfBlocks(NewHeap);
@@ -1451,14 +1846,13 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
 				 bool swap_toast_by_content,
 				 bool check_constraints,
 				 bool is_internal,
+				 bool reindex,
 				 TransactionId frozenXid,
 				 MultiXactId cutoffMulti,
 				 char newrelpersistence)
 {
 	ObjectAddress object;
 	Oid			mapped_tables[4];
-	int			reindex_flags;
-	ReindexParams reindex_params = {0};
 	int			i;
 
 	/* Report that we are now swapping relation files */
@@ -1484,39 +1878,47 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
 	if (is_system_catalog)
 		CacheInvalidateCatalog(OIDOldHeap);
 
-	/*
-	 * Rebuild each index on the relation (but not the toast table, which is
-	 * all-new at this point).  It is important to do this before the DROP
-	 * step because if we are processing a system catalog that will be used
-	 * during DROP, we want to have its indexes available.  There is no
-	 * advantage to the other order anyway because this is all transactional,
-	 * so no chance to reclaim disk space before commit.  We do not need a
-	 * final CommandCounterIncrement() because reindex_relation does it.
-	 *
-	 * Note: because index_build is called via reindex_relation, it will never
-	 * set indcheckxmin true for the indexes.  This is OK even though in some
-	 * sense we are building new indexes rather than rebuilding existing ones,
-	 * because the new heap won't contain any HOT chains at all, let alone
-	 * broken ones, so it can't be necessary to set indcheckxmin.
-	 */
-	reindex_flags = REINDEX_REL_SUPPRESS_INDEX_USE;
-	if (check_constraints)
-		reindex_flags |= REINDEX_REL_CHECK_CONSTRAINTS;
+	if (reindex)
+	{
+		int			reindex_flags;
+		ReindexParams reindex_params = {0};
 
-	/*
-	 * Ensure that the indexes have the same persistence as the parent
-	 * relation.
-	 */
-	if (newrelpersistence == RELPERSISTENCE_UNLOGGED)
-		reindex_flags |= REINDEX_REL_FORCE_INDEXES_UNLOGGED;
-	else if (newrelpersistence == RELPERSISTENCE_PERMANENT)
-		reindex_flags |= REINDEX_REL_FORCE_INDEXES_PERMANENT;
+		/*
+		 * Rebuild each index on the relation (but not the toast table, which
+		 * is all-new at this point).  It is important to do this before the
+		 * DROP step because if we are processing a system catalog that will
+		 * be used during DROP, we want to have its indexes available.  There
+		 * is no advantage to the other order anyway because this is all
+		 * transactional, so no chance to reclaim disk space before commit. We
+		 * do not need a final CommandCounterIncrement() because
+		 * reindex_relation does it.
+		 *
+		 * Note: because index_build is called via reindex_relation, it will
+		 * never set indcheckxmin true for the indexes.  This is OK even
+		 * though in some sense we are building new indexes rather than
+		 * rebuilding existing ones, because the new heap won't contain any
+		 * HOT chains at all, let alone broken ones, so it can't be necessary
+		 * to set indcheckxmin.
+		 */
+		reindex_flags = REINDEX_REL_SUPPRESS_INDEX_USE;
+		if (check_constraints)
+			reindex_flags |= REINDEX_REL_CHECK_CONSTRAINTS;
 
-	/* Report that we are now reindexing relations */
-	pgstat_progress_update_param(PROGRESS_REPACK_PHASE,
-								 PROGRESS_REPACK_PHASE_REBUILD_INDEX);
+		/*
+		 * Ensure that the indexes have the same persistence as the parent
+		 * relation.
+		 */
+		if (newrelpersistence == RELPERSISTENCE_UNLOGGED)
+			reindex_flags |= REINDEX_REL_FORCE_INDEXES_UNLOGGED;
+		else if (newrelpersistence == RELPERSISTENCE_PERMANENT)
+			reindex_flags |= REINDEX_REL_FORCE_INDEXES_PERMANENT;
 
-	reindex_relation(NULL, OIDOldHeap, reindex_flags, &reindex_params);
+		/* Report that we are now reindexing relations */
+		pgstat_progress_update_param(PROGRESS_REPACK_PHASE,
+									 PROGRESS_REPACK_PHASE_REBUILD_INDEX);
+
+		reindex_relation(NULL, OIDOldHeap, reindex_flags, &reindex_params);
+	}
 
 	/* Report that we are now doing clean up */
 	pgstat_progress_update_param(PROGRESS_REPACK_PHASE,
@@ -1859,7 +2261,8 @@ cluster_is_permitted_for_relation(RepackCommand cmd, Oid relid, Oid userid)
  * case, if an index name is given, it's up to the caller to resolve it.
  */
 static Relation
-process_single_relation(RepackStmt *stmt, ClusterParams *params)
+process_single_relation(RepackStmt *stmt, LOCKMODE lockmode, bool isTopLevel,
+						ClusterParams *params)
 {
 	Relation	rel;
 	Oid			tableOid;
@@ -1868,13 +2271,9 @@ process_single_relation(RepackStmt *stmt, ClusterParams *params)
 	Assert(stmt->command == REPACK_COMMAND_CLUSTER ||
 		   stmt->command == REPACK_COMMAND_REPACK);
 
-	/*
-	 * Find, lock, and check permissions on the table.  We obtain
-	 * AccessExclusiveLock right away to avoid lock-upgrade hazard in the
-	 * single-transaction case.
-	 */
+	/* Find, lock, and check permissions on the table. */
 	tableOid = RangeVarGetRelidExtended(stmt->relation->relation,
-										AccessExclusiveLock,
+										lockmode,
 										0,
 										RangeVarCallbackMaintainsTable,
 										NULL);
@@ -1906,13 +2305,14 @@ process_single_relation(RepackStmt *stmt, ClusterParams *params)
 		return rel;
 	else
 	{
-		Oid			indexOid;
+		Oid			indexOid = InvalidOid;
 
 		indexOid = determine_clustered_index(rel, stmt->usingindex,
 											 stmt->indexname);
 		if (OidIsValid(indexOid))
-			check_index_is_clusterable(rel, indexOid, AccessExclusiveLock);
-		cluster_rel(stmt->command, rel, indexOid, params);
+			check_index_is_clusterable(rel, indexOid, lockmode);
+
+		cluster_rel(stmt->command, rel, indexOid, params, isTopLevel);
 
 		/* Do an analyze, if requested */
 		if (params->options & CLUOPT_ANALYZE)
@@ -1995,3 +2395,1058 @@ RepackCommandAsString(RepackCommand cmd)
 	}
 	return "???";
 }
+
+
+/*
+ * Call this function before REPACK CONCURRENTLY starts to setup logical
+ * decoding. It makes sure that other users of the table put enough
+ * information into WAL.
+ *
+ * The point is that at various places we expect that the table we're
+ * processing is treated like a system catalog. For example, we need to be
+ * able to scan it using a "historic snapshot" anytime during the processing
+ * (as opposed to scanning only at the start point of the decoding, as logical
+ * replication does during initial table synchronization), in order to apply
+ * concurrent UPDATE / DELETE commands.
+ *
+ * Note that TOAST table needs no attention here as it's not scanned using
+ * historic snapshot.
+ */
+static void
+begin_concurrent_repack(Relation rel)
+{
+	Oid			toastrelid;
+
+	/*
+	 * Avoid logical decoding of other relations by this backend. The lock we
+	 * have guarantees that the actual locator cannot be changed concurrently:
+	 * TRUNCATE needs AccessExclusiveLock.
+	 */
+	Assert(CheckRelationLockedByMe(rel, ShareUpdateExclusiveLock, false));
+	repacked_rel_locator = rel->rd_locator;
+	toastrelid = rel->rd_rel->reltoastrelid;
+	if (OidIsValid(toastrelid))
+	{
+		Relation	toastrel;
+
+		/* Avoid logical decoding of other TOAST relations. */
+		toastrel = table_open(toastrelid, AccessShareLock);
+		repacked_rel_toast_locator = toastrel->rd_locator;
+		table_close(toastrel, AccessShareLock);
+	}
+}
+
+/*
+ * Call this when done with REPACK CONCURRENTLY.
+ */
+static void
+end_concurrent_repack(void)
+{
+	/*
+	 * Restore normal function of (future) logical decoding for this backend.
+	 */
+	repacked_rel_locator.relNumber = InvalidOid;
+	repacked_rel_toast_locator.relNumber = InvalidOid;
+}
+
+/*
+ * This function is much like pg_create_logical_replication_slot() except that
+ * the new slot is neither released (if anyone else could read changes from
+ * our slot, we could miss changes other backends do while we copy the
+ * existing data into temporary table), nor persisted (it's easier to handle
+ * crash by restarting all the work from scratch).
+ */
+static LogicalDecodingContext *
+setup_logical_decoding(Oid relid)
+{
+	Relation	rel;
+	TupleDesc	tupdesc;
+	LogicalDecodingContext *ctx;
+	RepackDecodingState *dstate = palloc0_object(RepackDecodingState);
+
+	/*
+	 * REPACK CONCURRENTLY is not allowed in a transaction block, so this
+	 * should never fire.
+	 */
+	Assert(!TransactionIdIsValid(GetTopTransactionIdIfAny()));
+
+	/*
+	 * A single backend should not execute multiple REPACK commands at a time,
+	 * so use PID to make the slot unique.
+	 */
+	snprintf(NameStr(dstate->slotname), NAMEDATALEN, "repack_%d", MyProcPid);
+
+	/*
+	 * Check if we can use logical decoding.
+	 */
+	CheckSlotPermissions();
+	CheckLogicalDecodingRequirements();
+
+	/* RS_TEMPORARY so that the slot gets cleaned up on ERROR. */
+	ReplicationSlotCreate(NameStr(dstate->slotname), true, RS_TEMPORARY,
+						  false, false, false);
+
+	/*
+	 * Neither prepare_write nor do_write callback nor update_progress is
+	 * useful for us.
+	 */
+	ctx = CreateInitDecodingContext(REPL_PLUGIN_NAME,
+									NIL,
+									true,
+									InvalidXLogRecPtr,
+									XL_ROUTINE(.page_read = read_local_xlog_page,
+											   .segment_open = wal_segment_open,
+											   .segment_close = wal_segment_close),
+									NULL, NULL, NULL);
+
+	/*
+	 * We don't have control on setting fast_forward, so at least check it.
+	 */
+	Assert(!ctx->fast_forward);
+
+	DecodingContextFindStartpoint(ctx);
+
+	/* Some WAL records should have been read. */
+	Assert(ctx->reader->EndRecPtr != InvalidXLogRecPtr);
+
+	XLByteToSeg(ctx->reader->EndRecPtr, repack_current_segment,
+				wal_segment_size);
+
+	/*
+	 * Setup structures to store decoded changes.
+	 */
+	dstate->relid = relid;
+	dstate->tstore = tuplestore_begin_heap(false, false,
+										   maintenance_work_mem);
+
+	/* Caller should already have the table locked. */
+	rel = table_open(relid, NoLock);
+	tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
+	dstate->tupdesc = tupdesc;
+	table_close(rel, NoLock);
+
+	/* Initialize the descriptor to store the changes ... */
+	dstate->tupdesc_change = CreateTemplateTupleDesc(1);
+
+	TupleDescInitEntry(dstate->tupdesc_change, 1, NULL, BYTEAOID, -1, 0);
+	/* ... as well as the corresponding slot. */
+	dstate->tsslot = MakeSingleTupleTableSlot(dstate->tupdesc_change,
+											  &TTSOpsMinimalTuple);
+
+	dstate->resowner = ResourceOwnerCreate(CurrentResourceOwner,
+										   "logical decoding");
+
+	ctx->output_writer_private = dstate;
+	return ctx;
+}
+
+/*
+ * Retrieve tuple from ConcurrentChange structure.
+ *
+ * The input data starts with the structure but it might not be appropriately
+ * aligned.
+ */
+static HeapTuple
+get_changed_tuple(char *change)
+{
+	HeapTupleData tup_data;
+	HeapTuple	result;
+	char	   *src;
+
+	/*
+	 * Ensure alignment before accessing the fields. (This is why we can't use
+	 * heap_copytuple() instead of this function.)
+	 */
+	src = change + offsetof(ConcurrentChange, tup_data);
+	memcpy(&tup_data, src, sizeof(HeapTupleData));
+
+	result = (HeapTuple) palloc(HEAPTUPLESIZE + tup_data.t_len);
+	memcpy(result, &tup_data, sizeof(HeapTupleData));
+	result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
+	src = change + SizeOfConcurrentChange;
+	memcpy(result->t_data, src, result->t_len);
+
+	return result;
+}
+
+/*
+ * Decode logical changes from the WAL sequence up to end_of_wal.
+ */
+void
+repack_decode_concurrent_changes(LogicalDecodingContext *ctx,
+								 XLogRecPtr end_of_wal)
+{
+	RepackDecodingState *dstate;
+	ResourceOwner resowner_old;
+
+	/*
+	 * Invalidate the "present" cache before moving to "(recent) history".
+	 */
+	InvalidateSystemCaches();
+
+	dstate = (RepackDecodingState *) ctx->output_writer_private;
+	resowner_old = CurrentResourceOwner;
+	CurrentResourceOwner = dstate->resowner;
+
+	PG_TRY();
+	{
+		while (ctx->reader->EndRecPtr < end_of_wal)
+		{
+			XLogRecord *record;
+			XLogSegNo	segno_new;
+			char	   *errm = NULL;
+			XLogRecPtr	end_lsn;
+
+			record = XLogReadRecord(ctx->reader, &errm);
+			if (errm)
+				elog(ERROR, "%s", errm);
+
+			if (record != NULL)
+				LogicalDecodingProcessRecord(ctx, ctx->reader);
+
+			/*
+			 * If WAL segment boundary has been crossed, inform the decoding
+			 * system that the catalog_xmin can advance. (We can confirm more
+			 * often, but a filling a single WAL segment should not take much
+			 * time.)
+			 */
+			end_lsn = ctx->reader->EndRecPtr;
+			XLByteToSeg(end_lsn, segno_new, wal_segment_size);
+			if (segno_new != repack_current_segment)
+			{
+				LogicalConfirmReceivedLocation(end_lsn);
+				elog(DEBUG1, "REPACK: confirmed receive location %X/%X",
+					 (uint32) (end_lsn >> 32), (uint32) end_lsn);
+				repack_current_segment = segno_new;
+			}
+
+			CHECK_FOR_INTERRUPTS();
+		}
+		InvalidateSystemCaches();
+		CurrentResourceOwner = resowner_old;
+	}
+	PG_CATCH();
+	{
+		/* clear all timetravel entries */
+		InvalidateSystemCaches();
+		CurrentResourceOwner = resowner_old;
+		PG_RE_THROW();
+	}
+	PG_END_TRY();
+}
+
+/*
+ * Apply changes that happened during the initial load.
+ *
+ * Scan key is passed by caller, so it does not have to be constructed
+ * multiple times. Key entries have all fields initialized, except for
+ * sk_argument.
+ */
+static void
+apply_concurrent_changes(RepackDecodingState *dstate, ChangeDest *dest)
+{
+	Relation	rel = dest->rel;
+	TupleTableSlot *index_slot,
+			   *ident_slot;
+	HeapTuple	tup_old = NULL;
+
+	if (dstate->nchanges == 0)
+		return;
+
+	/* TupleTableSlot is needed to pass the tuple to ExecInsertIndexTuples(). */
+	index_slot = MakeSingleTupleTableSlot(dstate->tupdesc, &TTSOpsHeapTuple);
+
+	/* A slot to fetch tuples from identity index. */
+	ident_slot = table_slot_create(rel, NULL);
+
+	while (tuplestore_gettupleslot(dstate->tstore, true, false,
+								   dstate->tsslot))
+	{
+		bool		shouldFree;
+		HeapTuple	tup_change,
+					tup,
+					tup_exist;
+		char	   *change_raw,
+				   *src;
+		ConcurrentChange change;
+		bool		isnull[1];
+		Datum		values[1];
+
+		CHECK_FOR_INTERRUPTS();
+
+		/* Get the change from the single-column tuple. */
+		tup_change = ExecFetchSlotHeapTuple(dstate->tsslot, false, &shouldFree);
+		heap_deform_tuple(tup_change, dstate->tupdesc_change, values, isnull);
+		Assert(!isnull[0]);
+
+		/* Make sure we access aligned data. */
+		change_raw = (char *) DatumGetByteaP(values[0]);
+		src = (char *) VARDATA(change_raw);
+		memcpy(&change, src, SizeOfConcurrentChange);
+
+		/*
+		 * Extract the tuple from the change. The tuple is copied here because
+		 * it might be assigned to 'tup_old', in which case it needs to
+		 * survive into the next iteration.
+		 */
+		tup = get_changed_tuple(src);
+
+		if (change.kind == CHANGE_UPDATE_OLD)
+		{
+			Assert(tup_old == NULL);
+			tup_old = tup;
+		}
+		else if (change.kind == CHANGE_INSERT)
+		{
+			Assert(tup_old == NULL);
+
+			apply_concurrent_insert(rel, &change, tup, dest->iistate,
+									index_slot);
+
+			pfree(tup);
+		}
+		else if (change.kind == CHANGE_UPDATE_NEW ||
+				 change.kind == CHANGE_DELETE)
+		{
+			HeapTuple	tup_key;
+
+			if (change.kind == CHANGE_UPDATE_NEW)
+			{
+				tup_key = tup_old != NULL ? tup_old : tup;
+			}
+			else
+			{
+				Assert(tup_old == NULL);
+				tup_key = tup;
+			}
+
+			/*
+			 * Find the tuple to be updated or deleted.
+			 */
+			tup_exist = find_target_tuple(rel, dest, tup_key, ident_slot);
+			if (tup_exist == NULL)
+				elog(ERROR, "Failed to find target tuple");
+
+			if (change.kind == CHANGE_UPDATE_NEW)
+				apply_concurrent_update(rel, tup, tup_exist, &change,
+										dest->iistate, index_slot);
+			else
+				apply_concurrent_delete(rel, tup_exist, &change);
+
+			if (tup_old != NULL)
+			{
+				pfree(tup_old);
+				tup_old = NULL;
+			}
+
+			pfree(tup);
+		}
+		else
+			elog(ERROR, "Unrecognized kind of change: %d", change.kind);
+
+		/*
+		 * If a change was applied now, increment CID for next writes and
+		 * update the snapshot so it sees the changes we've applied so far.
+		 */
+		if (change.kind != CHANGE_UPDATE_OLD)
+		{
+			CommandCounterIncrement();
+			UpdateActiveSnapshotCommandId();
+		}
+
+		/* TTSOpsMinimalTuple has .get_heap_tuple==NULL. */
+		Assert(shouldFree);
+		pfree(tup_change);
+	}
+
+	tuplestore_clear(dstate->tstore);
+	dstate->nchanges = 0;
+
+	/* Cleanup. */
+	ExecDropSingleTupleTableSlot(index_slot);
+	ExecDropSingleTupleTableSlot(ident_slot);
+}
+
+static void
+apply_concurrent_insert(Relation rel, ConcurrentChange *change, HeapTuple tup,
+						IndexInsertState *iistate, TupleTableSlot *index_slot)
+{
+	List	   *recheck;
+
+
+	/*
+	 * Like simple_heap_insert(), but make sure that the INSERT is not
+	 * logically decoded - see reform_and_rewrite_tuple() for more
+	 * information.
+	 */
+	heap_insert(rel, tup, GetCurrentCommandId(true), HEAP_INSERT_NO_LOGICAL,
+				NULL);
+
+	/*
+	 * Update indexes.
+	 *
+	 * In case functions in the index need the active snapshot and caller
+	 * hasn't set one.
+	 */
+	ExecStoreHeapTuple(tup, index_slot, false);
+	recheck = ExecInsertIndexTuples(iistate->rri,
+									index_slot,
+									iistate->estate,
+									false,	/* update */
+									false,	/* noDupErr */
+									NULL,	/* specConflict */
+									NIL,	/* arbiterIndexes */
+									false	/* onlySummarizing */
+		);
+
+	/*
+	 * If recheck is required, it must have been preformed on the source
+	 * relation by now. (All the logical changes we process here are already
+	 * committed.)
+	 */
+	list_free(recheck);
+
+	pgstat_progress_incr_param(PROGRESS_REPACK_HEAP_TUPLES_INSERTED, 1);
+}
+
+static void
+apply_concurrent_update(Relation rel, HeapTuple tup, HeapTuple tup_target,
+						ConcurrentChange *change, IndexInsertState *iistate,
+						TupleTableSlot *index_slot)
+{
+	LockTupleMode lockmode;
+	TM_FailureData tmfd;
+	TU_UpdateIndexes update_indexes;
+	TM_Result	res;
+	List	   *recheck;
+
+	/*
+	 * Write the new tuple into the new heap. ('tup' gets the TID assigned
+	 * here.)
+	 *
+	 * Do it like in simple_heap_update(), except for 'wal_logical' (and
+	 * except for 'wait').
+	 */
+	res = heap_update(rel, &tup_target->t_self, tup,
+					  GetCurrentCommandId(true),
+					  InvalidSnapshot,
+					  false,	/* no wait - only we are doing changes */
+					  &tmfd, &lockmode, &update_indexes,
+					  false /* wal_logical */ );
+	if (res != TM_Ok)
+		ereport(ERROR, (errmsg("failed to apply concurrent UPDATE")));
+
+	ExecStoreHeapTuple(tup, index_slot, false);
+
+	if (update_indexes != TU_None)
+	{
+		recheck = ExecInsertIndexTuples(iistate->rri,
+										index_slot,
+										iistate->estate,
+										true,	/* update */
+										false,	/* noDupErr */
+										NULL,	/* specConflict */
+										NIL,	/* arbiterIndexes */
+		/* onlySummarizing */
+										update_indexes == TU_Summarizing);
+		list_free(recheck);
+	}
+
+	pgstat_progress_incr_param(PROGRESS_REPACK_HEAP_TUPLES_UPDATED, 1);
+}
+
+static void
+apply_concurrent_delete(Relation rel, HeapTuple tup_target,
+						ConcurrentChange *change)
+{
+	TM_Result	res;
+	TM_FailureData tmfd;
+
+	/*
+	 * Delete tuple from the new heap.
+	 *
+	 * Do it like in simple_heap_delete(), except for 'wal_logical' (and
+	 * except for 'wait').
+	 */
+	res = heap_delete(rel, &tup_target->t_self, GetCurrentCommandId(true),
+					  InvalidSnapshot, false,
+					  &tmfd,
+					  false,	/* no wait - only we are doing changes */
+					  false /* wal_logical */ );
+
+	if (res != TM_Ok)
+		ereport(ERROR, (errmsg("failed to apply concurrent DELETE")));
+
+	pgstat_progress_incr_param(PROGRESS_REPACK_HEAP_TUPLES_DELETED, 1);
+}
+
+/*
+ * Find the tuple to be updated or deleted.
+ *
+ * 'tup_key' is a tuple containing the key values for the scan.
+ *
+ * On exit,'*scan_p' contains the scan descriptor used. The caller must close
+ * it when he no longer needs the tuple returned.
+ */
+static HeapTuple
+find_target_tuple(Relation rel, ChangeDest *dest, HeapTuple tup_key,
+				  TupleTableSlot *ident_slot)
+{
+	Relation	ident_index = dest->ident_index;
+	IndexScanDesc scan;
+	Form_pg_index ident_form;
+	int2vector *ident_indkey;
+	HeapTuple	result = NULL;
+
+	/* XXX no instrumentation for now */
+	scan = index_beginscan(rel, ident_index, GetActiveSnapshot(),
+						   NULL, dest->ident_key_nentries, 0);
+	index_rescan(scan, dest->ident_key, dest->ident_key_nentries, NULL, 0);
+
+	/* Info needed to retrieve key values from heap tuple. */
+	ident_form = ident_index->rd_index;
+	ident_indkey = &ident_form->indkey;
+
+	/* Use the incoming tuple to finalize the scan key. */
+	for (int i = 0; i < scan->numberOfKeys; i++)
+	{
+		ScanKey		entry;
+		bool		isnull;
+		int16		attno_heap;
+
+		entry = &scan->keyData[i];
+		attno_heap = ident_indkey->values[i];
+		entry->sk_argument = heap_getattr(tup_key,
+										  attno_heap,
+										  rel->rd_att,
+										  &isnull);
+		Assert(!isnull);
+	}
+	if (index_getnext_slot(scan, ForwardScanDirection, ident_slot))
+	{
+		bool		shouldFree;
+
+		result = ExecFetchSlotHeapTuple(ident_slot, false, &shouldFree);
+		/* TTSOpsBufferHeapTuple has .get_heap_tuple != NULL. */
+		Assert(!shouldFree);
+	}
+	index_endscan(scan);
+
+	return result;
+}
+
+/*
+ * Decode and apply concurrent changes.
+ */
+static void
+process_concurrent_changes(LogicalDecodingContext *decoding_ctx,
+						   XLogRecPtr end_of_wal, ChangeDest *dest)
+{
+	RepackDecodingState *dstate;
+
+	pgstat_progress_update_param(PROGRESS_REPACK_PHASE,
+								 PROGRESS_REPACK_PHASE_CATCH_UP);
+
+	dstate = (RepackDecodingState *) decoding_ctx->output_writer_private;
+
+	repack_decode_concurrent_changes(decoding_ctx, end_of_wal);
+
+	if (dstate->nchanges == 0)
+		return;
+
+	PG_TRY();
+	{
+		/*
+		 * Make sure that TOAST values can eventually be accessed via the old
+		 * relation - see comment in copy_table_data().
+		 */
+		if (OidIsValid(dest->toastrelid))
+			dest->rel->rd_toastoid = dest->toastrelid;
+
+		apply_concurrent_changes(dstate, dest);
+	}
+
+	/*
+	 * TODO Consider if the setting needs to be reverted: rel_dst will
+	 * eventually be dropped, w/o other transactions being able to access it.
+	 */
+	PG_FINALLY();
+	{
+		if (OidIsValid(dest->toastrelid))
+			dest->rel->rd_toastoid = InvalidOid;
+	}
+	PG_END_TRY();
+}
+
+/*
+ * Initialize IndexInsertState for index specified by ident_index_id.
+ *
+ * While doing that, also return the identity index in *ident_index_p.
+ */
+static IndexInsertState *
+get_index_insert_state(Relation relation, Oid ident_index_id,
+					   Relation *ident_index_p)
+{
+	EState	   *estate;
+	int			i;
+	IndexInsertState *result;
+	Relation	ident_index = NULL;
+
+	result = (IndexInsertState *) palloc0(sizeof(IndexInsertState));
+	estate = CreateExecutorState();
+
+	result->rri = (ResultRelInfo *) palloc(sizeof(ResultRelInfo));
+	InitResultRelInfo(result->rri, relation, 0, 0, 0);
+	ExecOpenIndices(result->rri, false);
+
+	/*
+	 * Find the relcache entry of the identity index so that we spend no extra
+	 * effort to open / close it.
+	 */
+	for (i = 0; i < result->rri->ri_NumIndices; i++)
+	{
+		Relation	ind_rel;
+
+		ind_rel = result->rri->ri_IndexRelationDescs[i];
+		if (ind_rel->rd_id == ident_index_id)
+			ident_index = ind_rel;
+	}
+	if (ident_index == NULL)
+		elog(ERROR, "Failed to open identity index");
+
+	/* Only initialize fields needed by ExecInsertIndexTuples(). */
+	result->estate = estate;
+
+	*ident_index_p = ident_index;
+	return result;
+}
+
+/*
+ * Build scan key to process logical changes.
+ */
+static ScanKey
+build_identity_key(Oid ident_idx_oid, Relation rel_src, int *nentries)
+{
+	Relation	ident_idx_rel;
+	Form_pg_index ident_idx;
+	int			n,
+				i;
+	ScanKey		result;
+
+	Assert(OidIsValid(ident_idx_oid));
+	ident_idx_rel = index_open(ident_idx_oid, AccessShareLock);
+	ident_idx = ident_idx_rel->rd_index;
+	n = ident_idx->indnatts;
+	result = (ScanKey) palloc(sizeof(ScanKeyData) * n);
+	for (i = 0; i < n; i++)
+	{
+		ScanKey		entry;
+		int16		relattno;
+		Form_pg_attribute att;
+		Oid			opfamily,
+					opcintype,
+					opno,
+					opcode;
+
+		entry = &result[i];
+		relattno = ident_idx->indkey.values[i];
+		if (relattno >= 1)
+		{
+			TupleDesc	desc;
+
+			desc = rel_src->rd_att;
+			att = TupleDescAttr(desc, relattno - 1);
+		}
+		else
+			elog(ERROR, "Unexpected attribute number %d in index", relattno);
+
+		opfamily = ident_idx_rel->rd_opfamily[i];
+		opcintype = ident_idx_rel->rd_opcintype[i];
+		opno = get_opfamily_member(opfamily, opcintype, opcintype,
+								   BTEqualStrategyNumber);
+
+		if (!OidIsValid(opno))
+			elog(ERROR, "Failed to find = operator for type %u", opcintype);
+
+		opcode = get_opcode(opno);
+		if (!OidIsValid(opcode))
+			elog(ERROR, "Failed to find = operator for operator %u", opno);
+
+		/* Initialize everything but argument. */
+		ScanKeyInit(entry,
+					i + 1,
+					BTEqualStrategyNumber, opcode,
+					(Datum) NULL);
+		entry->sk_collation = att->attcollation;
+	}
+	index_close(ident_idx_rel, AccessShareLock);
+
+	*nentries = n;
+	return result;
+}
+
+static void
+free_index_insert_state(IndexInsertState *iistate)
+{
+	ExecCloseIndices(iistate->rri);
+	FreeExecutorState(iistate->estate);
+	pfree(iistate->rri);
+	pfree(iistate);
+}
+
+static void
+cleanup_logical_decoding(LogicalDecodingContext *ctx)
+{
+	RepackDecodingState *dstate;
+
+	dstate = (RepackDecodingState *) ctx->output_writer_private;
+
+	ExecDropSingleTupleTableSlot(dstate->tsslot);
+	FreeTupleDesc(dstate->tupdesc_change);
+	FreeTupleDesc(dstate->tupdesc);
+	tuplestore_end(dstate->tstore);
+
+	FreeDecodingContext(ctx);
+
+	ReplicationSlotRelease();
+	ReplicationSlotDrop(NameStr(dstate->slotname), false);
+	pfree(dstate);
+}
+
+/*
+ * The final steps of rebuild_relation() for concurrent processing.
+ *
+ * On entry, NewHeap is locked in AccessExclusiveLock mode. OldHeap and its
+ * clustering index (if one is passed) are still locked in a mode that allows
+ * concurrent data changes. On exit, both tables and their indexes are closed,
+ * but locked in AccessExclusiveLock mode.
+ */
+static void
+rebuild_relation_finish_concurrent(Relation NewHeap, Relation OldHeap,
+								   Relation cl_index,
+								   LogicalDecodingContext *decoding_ctx,
+								   bool swap_toast_by_content,
+								   TransactionId frozenXid,
+								   MultiXactId cutoffMulti)
+{
+	LOCKMODE	lockmode_old PG_USED_FOR_ASSERTS_ONLY;
+	List	   *ind_oids_new;
+	Oid			old_table_oid = RelationGetRelid(OldHeap);
+	Oid			new_table_oid = RelationGetRelid(NewHeap);
+	List	   *ind_oids_old = RelationGetIndexList(OldHeap);
+	ListCell   *lc,
+			   *lc2;
+	char		relpersistence;
+	bool		is_system_catalog;
+	Oid			ident_idx_old,
+				ident_idx_new;
+	XLogRecPtr	wal_insert_ptr,
+				end_of_wal;
+	char		dummy_rec_data = '\0';
+	Relation   *ind_refs,
+			   *ind_refs_p;
+	int			nind;
+	ChangeDest	chgdst;
+
+	/* Like in cluster_rel(). */
+	lockmode_old = ShareUpdateExclusiveLock;
+	Assert(CheckRelationLockedByMe(OldHeap, lockmode_old, false));
+	Assert(cl_index == NULL ||
+		   CheckRelationLockedByMe(cl_index, lockmode_old, false));
+	/* This is expected from the caller. */
+	Assert(CheckRelationLockedByMe(NewHeap, AccessExclusiveLock, false));
+
+	ident_idx_old = RelationGetReplicaIndex(OldHeap);
+
+	/*
+	 * Unlike the exclusive case, we build new indexes for the new relation
+	 * rather than swapping the storage and reindexing the old relation. The
+	 * point is that the index build can take some time, so we do it before we
+	 * get AccessExclusiveLock on the old heap and therefore we cannot swap
+	 * the heap storage yet.
+	 *
+	 * index_create() will lock the new indexes using AccessExclusiveLock - no
+	 * need to change that.
+	 *
+	 * We assume that ShareUpdateExclusiveLock on the table prevents anyone
+	 * from dropping the existing indexes or adding new ones, so the lists of
+	 * old and new indexes should match at the swap time. On the other hand we
+	 * do not block ALTER INDEX commands that do not require table lock (e.g.
+	 * ALTER INDEX ... SET ...).
+	 *
+	 * XXX Should we check a the end of our work if another transaction
+	 * executed such a command and issue a NOTICE that we might have discarded
+	 * its effects? (For example, someone changes storage parameter after we
+	 * have created the new index, the new value of that parameter is lost.)
+	 * Alternatively, we can lock all the indexes now in a mode that blocks
+	 * all the ALTER INDEX commands (ShareUpdateExclusiveLock ?), and keep
+	 * them locked till the end of the transactions. That might increase the
+	 * risk of deadlock during the lock upgrade below, however SELECT / DML
+	 * queries should not be involved in such a deadlock.
+	 */
+	ind_oids_new = build_new_indexes(NewHeap, OldHeap, ind_oids_old);
+
+	/*
+	 * Processing shouldn't start w/o valid identity index.
+	 */
+	Assert(OidIsValid(ident_idx_old));
+
+	/* Find "identity index" on the new relation. */
+	ident_idx_new = InvalidOid;
+	forboth(lc, ind_oids_old, lc2, ind_oids_new)
+	{
+		Oid			ind_old = lfirst_oid(lc);
+		Oid			ind_new = lfirst_oid(lc2);
+
+		if (ident_idx_old == ind_old)
+		{
+			ident_idx_new = ind_new;
+			break;
+		}
+	}
+	if (!OidIsValid(ident_idx_new))
+
+		/*
+		 * Should not happen, given our lock on the old relation.
+		 */
+		ereport(ERROR,
+				(errmsg("Identity index missing on the new relation")));
+
+	/* Gather information to apply concurrent changes. */
+	chgdst.rel = NewHeap;
+	chgdst.toastrelid = swap_toast_by_content ?
+		OldHeap->rd_rel->reltoastrelid : InvalidOid;
+	chgdst.iistate = get_index_insert_state(NewHeap, ident_idx_new,
+											&chgdst.ident_index);
+	chgdst.ident_key = build_identity_key(ident_idx_new, OldHeap,
+										  &chgdst.ident_key_nentries);
+
+	/*
+	 * During testing, wait for another backend to perform concurrent data
+	 * changes which we will process below.
+	 */
+	INJECTION_POINT("repack-concurrently-before-lock", NULL);
+
+	/*
+	 * Flush all WAL records inserted so far (possibly except for the last
+	 * incomplete page, see GetInsertRecPtr), to minimize the amount of data
+	 * we need to flush while holding exclusive lock on the source table.
+	 */
+	wal_insert_ptr = GetInsertRecPtr();
+	XLogFlush(wal_insert_ptr);
+	end_of_wal = GetFlushRecPtr(NULL);
+
+	/*
+	 * Apply concurrent changes first time, to minimize the time we need to
+	 * hold AccessExclusiveLock. (Quite some amount of WAL could have been
+	 * written during the data copying and index creation.)
+	 */
+	process_concurrent_changes(decoding_ctx, end_of_wal, &chgdst);
+
+	/*
+	 * Acquire AccessExclusiveLock on the table, its TOAST relation (if there
+	 * is one), all its indexes, so that we can swap the files.
+	 *
+	 * Before that, unlock the index temporarily to avoid deadlock in case
+	 * another transaction is trying to lock it while holding the lock on the
+	 * table.
+	 */
+	if (cl_index)
+	{
+		index_close(cl_index, ShareUpdateExclusiveLock);
+		cl_index = NULL;
+	}
+	/* For the same reason, unlock TOAST relation. */
+	if (OldHeap->rd_rel->reltoastrelid)
+		LockRelationOid(OldHeap->rd_rel->reltoastrelid, AccessExclusiveLock);
+	/* Finally lock the table */
+	LockRelationOid(old_table_oid, AccessExclusiveLock);
+
+	/*
+	 * Lock all indexes now, not only the clustering one: all indexes need to
+	 * have their files swapped. While doing that, store their relation
+	 * references in an array, to handle predicate locks below.
+	 */
+	ind_refs_p = ind_refs = palloc_array(Relation, list_length(ind_oids_old));
+	nind = 0;
+	foreach(lc, ind_oids_old)
+	{
+		Oid			ind_oid;
+		Relation	index;
+
+		ind_oid = lfirst_oid(lc);
+		index = index_open(ind_oid, AccessExclusiveLock);
+
+		/*
+		 * TODO 1) Do we need to check if ALTER INDEX was executed since the
+		 * new index was created in build_new_indexes()? 2) Specifically for
+		 * the clustering index, should check_index_is_clusterable() be called
+		 * here? (Not sure about the latter: ShareUpdateExclusiveLock on the
+		 * table probably blocks all commands that affect the result of
+		 * check_index_is_clusterable().)
+		 */
+		*ind_refs_p = index;
+		ind_refs_p++;
+		nind++;
+	}
+
+	/*
+	 * In addition, lock the OldHeap's TOAST relation exclusively - again, the
+	 * lock is needed to swap the files.
+	 */
+	if (OidIsValid(OldHeap->rd_rel->reltoastrelid))
+		LockRelationOid(OldHeap->rd_rel->reltoastrelid, AccessExclusiveLock);
+
+	/*
+	 * Tuples and pages of the old heap will be gone, but the heap will stay.
+	 */
+	TransferPredicateLocksToHeapRelation(OldHeap);
+	/* The same for indexes. */
+	for (int i = 0; i < nind; i++)
+	{
+		Relation	index = ind_refs[i];
+
+		TransferPredicateLocksToHeapRelation(index);
+
+		/*
+		 * References to indexes on the old relation are not needed anymore,
+		 * however locks stay till the end of the transaction.
+		 */
+		index_close(index, NoLock);
+	}
+	pfree(ind_refs);
+
+	/*
+	 * Flush anything we see in WAL, to make sure that all changes committed
+	 * while we were waiting for the exclusive lock are available for
+	 * decoding. This should not be necessary if all backends had
+	 * synchronous_commit set, but we can't rely on this setting.
+	 *
+	 * Unfortunately, GetInsertRecPtr() may lag behind the actual insert
+	 * position, and GetLastImportantRecPtr() points at the start of the last
+	 * record rather than at the end. Thus the simplest way to determine the
+	 * insert position is to insert a dummy record and use its LSN.
+	 *
+	 * XXX Consider using GetLastImportantRecPtr() and adding the size of the
+	 * last record (plus the total size of all the page headers the record
+	 * spans)?
+	 */
+	XLogBeginInsert();
+	XLogRegisterData(&dummy_rec_data, 1);
+	wal_insert_ptr = XLogInsert(RM_XLOG_ID, XLOG_NOOP);
+	XLogFlush(wal_insert_ptr);
+	end_of_wal = GetFlushRecPtr(NULL);
+
+	/* Apply the concurrent changes again. */
+	process_concurrent_changes(decoding_ctx, end_of_wal, &chgdst);
+
+	/* Remember info about rel before closing OldHeap */
+	relpersistence = OldHeap->rd_rel->relpersistence;
+	is_system_catalog = IsSystemRelation(OldHeap);
+
+	pgstat_progress_update_param(PROGRESS_REPACK_PHASE,
+								 PROGRESS_REPACK_PHASE_SWAP_REL_FILES);
+
+	/*
+	 * Even ShareUpdateExclusiveLock should have prevented others from
+	 * creating / dropping indexes (even using the CONCURRENTLY option), so we
+	 * do not need to check whether the lists match.
+	 */
+	forboth(lc, ind_oids_old, lc2, ind_oids_new)
+	{
+		Oid			ind_old = lfirst_oid(lc);
+		Oid			ind_new = lfirst_oid(lc2);
+		Oid			mapped_tables[4];
+
+		/* Zero out possible results from swapped_relation_files */
+		memset(mapped_tables, 0, sizeof(mapped_tables));
+
+		swap_relation_files(ind_old, ind_new,
+							(old_table_oid == RelationRelationId),
+							swap_toast_by_content,
+							true,
+							InvalidTransactionId,
+							InvalidMultiXactId,
+							mapped_tables);
+
+#ifdef USE_ASSERT_CHECKING
+
+		/*
+		 * Concurrent processing is not supported for system relations, so
+		 * there should be no mapped tables.
+		 */
+		for (int i = 0; i < 4; i++)
+			Assert(mapped_tables[i] == 0);
+#endif
+	}
+
+	/* The new indexes must be visible for deletion. */
+	CommandCounterIncrement();
+
+	/* Close the old heap but keep lock until transaction commit. */
+	table_close(OldHeap, NoLock);
+	/* Close the new heap. (We didn't have to open its indexes). */
+	table_close(NewHeap, NoLock);
+
+	/* Cleanup what we don't need anymore. (And close the identity index.) */
+	pfree(chgdst.ident_key);
+	free_index_insert_state(chgdst.iistate);
+
+	/*
+	 * Swap the relations and their TOAST relations and TOAST indexes. This
+	 * also drops the new relation and its indexes.
+	 *
+	 * (System catalogs are currently not supported.)
+	 */
+	Assert(!is_system_catalog);
+	finish_heap_swap(old_table_oid, new_table_oid,
+					 is_system_catalog,
+					 swap_toast_by_content,
+					 false, true, false,
+					 frozenXid, cutoffMulti,
+					 relpersistence);
+}
+
+/*
+ * Build indexes on NewHeap according to those on OldHeap.
+ *
+ * OldIndexes is the list of index OIDs on OldHeap.
+ *
+ * A list of OIDs of the corresponding indexes created on NewHeap is
+ * returned. The order of items does match, so we can use these arrays to swap
+ * index storage.
+ */
+static List *
+build_new_indexes(Relation NewHeap, Relation OldHeap, List *OldIndexes)
+{
+	ListCell   *lc;
+	List	   *result = NIL;
+
+	pgstat_progress_update_param(PROGRESS_REPACK_PHASE,
+								 PROGRESS_REPACK_PHASE_REBUILD_INDEX);
+
+	foreach(lc, OldIndexes)
+	{
+		Oid			ind_oid,
+					ind_oid_new;
+		char	   *newName;
+		Relation	ind;
+
+		ind_oid = lfirst_oid(lc);
+		ind = index_open(ind_oid, AccessShareLock);
+
+		newName = ChooseRelationName(get_rel_name(ind_oid),
+									 NULL,
+									 "repacknew",
+									 get_rel_namespace(ind->rd_index->indrelid),
+									 false);
+		ind_oid_new = index_create_copy(NewHeap, ind_oid,
+										ind->rd_rel->reltablespace, newName,
+										false);
+		result = lappend_oid(result, ind_oid_new);
+
+		index_close(ind, AccessShareLock);
+	}
+
+	return result;
+}
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index ef7c0d624f1..d12e2d0f2e0 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -892,7 +892,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 static void
 refresh_by_heap_swap(Oid matviewOid, Oid OIDNewHeap, char relpersistence)
 {
-	finish_heap_swap(matviewOid, OIDNewHeap, false, false, true, true,
+	finish_heap_swap(matviewOid, OIDNewHeap, false, false, true, true, true,
 					 RecentXmin, ReadNextMultiXactId(), relpersistence);
 }
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 07e5b95782e..1bce85e4232 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5992,6 +5992,7 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
 			finish_heap_swap(tab->relid, OIDNewHeap,
 							 false, false, true,
 							 !OidIsValid(tab->newTableSpace),
+							 true,
 							 RecentXmin,
 							 ReadNextMultiXactId(),
 							 persistence);
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 827e66724b5..03478ecd5cc 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -126,7 +126,7 @@ static void vac_truncate_clog(TransactionId frozenXID,
 							  TransactionId lastSaneFrozenXid,
 							  MultiXactId lastSaneMinMulti);
 static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
-					   BufferAccessStrategy bstrategy);
+					   BufferAccessStrategy bstrategy, bool isTopLevel);
 static double compute_parallel_delay(void);
 static VacOptValue get_vacoptval_from_boolean(DefElem *def);
 static bool vac_tid_reaped(ItemPointer itemptr, void *state);
@@ -627,7 +627,8 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 
 			if (params.options & VACOPT_VACUUM)
 			{
-				if (!vacuum_rel(vrel->oid, vrel->relation, params, bstrategy))
+				if (!vacuum_rel(vrel->oid, vrel->relation, params, bstrategy,
+								isTopLevel))
 					continue;
 			}
 
@@ -1997,7 +1998,7 @@ vac_truncate_clog(TransactionId frozenXID,
  */
 static bool
 vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
-		   BufferAccessStrategy bstrategy)
+		   BufferAccessStrategy bstrategy, bool isTopLevel)
 {
 	LOCKMODE	lmode;
 	Relation	rel;
@@ -2288,7 +2289,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 
 			/* VACUUM FULL is a variant of REPACK; see cluster.c */
 			cluster_rel(REPACK_COMMAND_VACUUMFULL, rel, InvalidOid,
-						&cluster_params);
+						&cluster_params, isTopLevel);
 			/* cluster_rel closes the relation, but keeps lock */
 
 			rel = NULL;
@@ -2331,7 +2332,8 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 		toast_vacuum_params.options |= VACOPT_PROCESS_MAIN;
 		toast_vacuum_params.toast_parent = relid;
 
-		vacuum_rel(toast_relid, NULL, toast_vacuum_params, bstrategy);
+		vacuum_rel(toast_relid, NULL, toast_vacuum_params, bstrategy,
+				   isTopLevel);
 	}
 
 	/*
diff --git a/src/backend/meson.build b/src/backend/meson.build
index b831a541652..5c148131217 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -194,5 +194,6 @@ pg_test_mod_args = pg_mod_args + {
 subdir('jit/llvm')
 subdir('replication/libpqwalreceiver')
 subdir('replication/pgoutput')
+subdir('replication/pgoutput_repack')
 subdir('snowball')
 subdir('utils/mb/conversion_procs')
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index cc03f0706e9..73fc4d30c67 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -33,6 +33,7 @@
 #include "access/xlogreader.h"
 #include "access/xlogrecord.h"
 #include "catalog/pg_control.h"
+#include "commands/cluster.h"
 #include "replication/decode.h"
 #include "replication/logical.h"
 #include "replication/message.h"
@@ -472,6 +473,88 @@ heap_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 	TransactionId xid = XLogRecGetXid(buf->record);
 	SnapBuild  *builder = ctx->snapshot_builder;
 
+	/*
+	 * If the change is not intended for logical decoding, do not even
+	 * establish transaction for it - REPACK CONCURRENTLY is the typical use
+	 * case.
+	 *
+	 * First, check if REPACK CONCURRENTLY is being performed by this backend.
+	 * If so, only decode data changes of the table that it is processing, and
+	 * the changes of its TOAST relation.
+	 *
+	 * (TOAST locator should not be set unless the main is.)
+	 */
+	Assert(!OidIsValid(repacked_rel_toast_locator.relNumber) ||
+		   OidIsValid(repacked_rel_locator.relNumber));
+
+	if (OidIsValid(repacked_rel_locator.relNumber))
+	{
+		XLogReaderState *r = buf->record;
+		RelFileLocator locator;
+
+		/* Not all records contain the block. */
+		if (XLogRecGetBlockTagExtended(r, 0, &locator, NULL, NULL, NULL) &&
+			!RelFileLocatorEquals(locator, repacked_rel_locator) &&
+			(!OidIsValid(repacked_rel_toast_locator.relNumber) ||
+			 !RelFileLocatorEquals(locator, repacked_rel_toast_locator)))
+			return;
+	}
+
+	/*
+	 * Second, skip records which do not contain sufficient information for
+	 * the decoding.
+	 *
+	 * The problem we solve here is that REPACK CONCURRENTLY generates WAL
+	 * when doing changes in the new table. Those changes should not be useful
+	 * for any other user (such as logical replication subscription) because
+	 * the new table will eventually be dropped (after REPACK CONCURRENTLY has
+	 * assigned its file to the "old table").
+	 */
+	switch (info)
+	{
+		case XLOG_HEAP_INSERT:
+			{
+				xl_heap_insert *rec;
+
+				rec = (xl_heap_insert *) XLogRecGetData(buf->record);
+
+				/*
+				 * This does happen when 1) raw_heap_insert marks the TOAST
+				 * record as HEAP_INSERT_NO_LOGICAL, 2) REPACK CONCURRENTLY
+				 * replays inserts performed by other backends.
+				 */
+				if ((rec->flags & XLH_INSERT_CONTAINS_NEW_TUPLE) == 0)
+					return;
+
+				break;
+			}
+
+		case XLOG_HEAP_HOT_UPDATE:
+		case XLOG_HEAP_UPDATE:
+			{
+				xl_heap_update *rec;
+
+				rec = (xl_heap_update *) XLogRecGetData(buf->record);
+				if ((rec->flags &
+					 (XLH_UPDATE_CONTAINS_NEW_TUPLE |
+					  XLH_UPDATE_CONTAINS_OLD_TUPLE |
+					  XLH_UPDATE_CONTAINS_OLD_KEY)) == 0)
+					return;
+
+				break;
+			}
+
+		case XLOG_HEAP_DELETE:
+			{
+				xl_heap_delete *rec;
+
+				rec = (xl_heap_delete *) XLogRecGetData(buf->record);
+				if (rec->flags & XLH_DELETE_NO_LOGICAL)
+					return;
+				break;
+			}
+	}
+
 	ReorderBufferProcessXid(ctx->reorder, xid, buf->origptr);
 
 	/*
@@ -512,6 +595,16 @@ heap_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 			break;
 
 		case XLOG_HEAP_TRUNCATE:
+			/* Is REPACK (CONCURRENTLY) being run by this backend? */
+			if (OidIsValid(repacked_rel_locator.relNumber))
+				/*
+				 * TRUNCATE changes rd_locator of the relation, so it'd break
+				 * REPACK (CONCURRENTLY). In fact it should not happen because
+				 * TRUNCATE needs AccessExclusiveLock on the table. Should we
+				 * only use Assert() here?
+				 */
+				ereport(ERROR,
+						(errmsg("TRUNCATE encountered while doing REPACK (CONCURRENTLY)")));
 			if (SnapBuildProcessChange(builder, xid, buf->origptr) &&
 				!ctx->fast_forward)
 				DecodeTruncate(ctx, buf);
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index dcf32101c4c..63efb577975 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -486,12 +486,33 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
 	return SnapBuildMVCCFromHistoric(snap, true);
 }
 
+/*
+ * Build an MVCC snapshot for the initial data load performed by REPACK
+ * CONCURRENTLY command.
+ *
+ * The snapshot will only be used to scan one particular relation, which is
+ * treated like a catalog (therefore ->building_full_snapshot is not
+ * important), and the caller should already have a replication slot setup (so
+ * we do not set MyProc->xmin). XXX Do we yet need to add some restrictions?
+ */
+Snapshot
+SnapBuildInitialSnapshotForRepack(SnapBuild *builder)
+{
+	Snapshot	snap;
+
+	Assert(builder->state == SNAPBUILD_CONSISTENT);
+	Assert(builder->building_full_snapshot);
+
+	snap = SnapBuildBuildSnapshot(builder);
+	return SnapBuildMVCCFromHistoric(snap, false);
+}
+
 /*
  * Turn a historic MVCC snapshot into an ordinary MVCC snapshot.
  *
  * Unlike a regular (non-historic) MVCC snapshot, the xip array of this
  * snapshot contains not only running main transactions, but also their
- * subtransactions. This difference does has no impact on XidInMVCCSnapshot().
+ * subtransactions. This difference has no impact on XidInMVCCSnapshot().
  *
  * Pass true for 'in_place' if you don't care about modifying the source
  * snapshot. If you need a new instance, and one that was allocated as a
diff --git a/src/backend/replication/pgoutput_repack/Makefile b/src/backend/replication/pgoutput_repack/Makefile
new file mode 100644
index 00000000000..4efeb713b70
--- /dev/null
+++ b/src/backend/replication/pgoutput_repack/Makefile
@@ -0,0 +1,32 @@
+#-------------------------------------------------------------------------
+#
+# Makefile--
+#    Makefile for src/backend/replication/pgoutput_repack
+#
+# IDENTIFICATION
+#    src/backend/replication/pgoutput_repack
+#
+#-------------------------------------------------------------------------
+
+subdir = src/backend/replication/pgoutput_repack
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+	$(WIN32RES) \
+	pgoutput_repack.o
+PGFILEDESC = "pgoutput_repack - logical replication output plugin for REPACK command"
+NAME = pgoutput_repack
+
+all: all-shared-lib
+
+include $(top_srcdir)/src/Makefile.shlib
+
+install: all installdirs install-lib
+
+installdirs: installdirs-lib
+
+uninstall: uninstall-lib
+
+clean distclean: clean-lib
+	rm -f $(OBJS)
diff --git a/src/backend/replication/pgoutput_repack/meson.build b/src/backend/replication/pgoutput_repack/meson.build
new file mode 100644
index 00000000000..133e865a4a0
--- /dev/null
+++ b/src/backend/replication/pgoutput_repack/meson.build
@@ -0,0 +1,18 @@
+# Copyright (c) 2022-2024, PostgreSQL Global Development Group
+
+pgoutput_repack_sources = files(
+  'pgoutput_repack.c',
+)
+
+if host_system == 'windows'
+  pgoutput_repack_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
+    '--NAME', 'pgoutput_repack',
+    '--FILEDESC', 'pgoutput_repack - logical replication output plugin for REPACK command',])
+endif
+
+pgoutput_repack = shared_module('pgoutput_repack',
+  pgoutput_repack_sources,
+  kwargs: pg_mod_args,
+)
+
+backend_targets += pgoutput_repack
diff --git a/src/backend/replication/pgoutput_repack/pgoutput_repack.c b/src/backend/replication/pgoutput_repack/pgoutput_repack.c
new file mode 100644
index 00000000000..178e47bdce4
--- /dev/null
+++ b/src/backend/replication/pgoutput_repack/pgoutput_repack.c
@@ -0,0 +1,248 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgoutput_repack.c
+ *		Logical Replication output plugin for REPACK command
+ *
+ * Copyright (c) 2012-2024, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		  src/backend/replication/pgoutput_repack/pgoutput_repack.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heaptoast.h"
+#include "commands/cluster.h"
+#include "replication/snapbuild.h"
+
+PG_MODULE_MAGIC;
+
+static void plugin_startup(LogicalDecodingContext *ctx,
+						   OutputPluginOptions *opt, bool is_init);
+static void plugin_shutdown(LogicalDecodingContext *ctx);
+static void plugin_begin_txn(LogicalDecodingContext *ctx,
+							 ReorderBufferTXN *txn);
+static void plugin_commit_txn(LogicalDecodingContext *ctx,
+							  ReorderBufferTXN *txn, XLogRecPtr commit_lsn);
+static void plugin_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
+						  Relation rel, ReorderBufferChange *change);
+static void store_change(LogicalDecodingContext *ctx,
+						 ConcurrentChangeKind kind, HeapTuple tuple);
+
+void
+_PG_output_plugin_init(OutputPluginCallbacks *cb)
+{
+	AssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);
+
+	cb->startup_cb = plugin_startup;
+	cb->begin_cb = plugin_begin_txn;
+	cb->change_cb = plugin_change;
+	cb->commit_cb = plugin_commit_txn;
+	cb->shutdown_cb = plugin_shutdown;
+}
+
+
+/* initialize this plugin */
+static void
+plugin_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
+			   bool is_init)
+{
+	ctx->output_plugin_private = NULL;
+
+	/* Probably unnecessary, as we don't use the SQL interface ... */
+	opt->output_type = OUTPUT_PLUGIN_BINARY_OUTPUT;
+
+	if (ctx->output_plugin_options != NIL)
+	{
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("This plugin does not expect any options")));
+	}
+}
+
+static void
+plugin_shutdown(LogicalDecodingContext *ctx)
+{
+}
+
+/*
+ * As we don't release the slot during processing of particular table, there's
+ * no room for SQL interface, even for debugging purposes. Therefore we need
+ * neither OutputPluginPrepareWrite() nor OutputPluginWrite() in the plugin
+ * callbacks. (Although we might want to write custom callbacks, this API
+ * seems to be unnecessarily generic for our purposes.)
+ */
+
+/* BEGIN callback */
+static void
+plugin_begin_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
+{
+}
+
+/* COMMIT callback */
+static void
+plugin_commit_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
+				  XLogRecPtr commit_lsn)
+{
+}
+
+/*
+ * Callback for individual changed tuples
+ */
+static void
+plugin_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
+			  Relation relation, ReorderBufferChange *change)
+{
+	RepackDecodingState *dstate;
+
+	dstate = (RepackDecodingState *) ctx->output_writer_private;
+
+	/* Only interested in one particular relation. */
+	if (relation->rd_id != dstate->relid)
+		return;
+
+	/* Decode entry depending on its type */
+	switch (change->action)
+	{
+		case REORDER_BUFFER_CHANGE_INSERT:
+			{
+				HeapTuple	newtuple;
+
+				newtuple = change->data.tp.newtuple != NULL ?
+					change->data.tp.newtuple : NULL;
+
+				/*
+				 * Identity checks in the main function should have made this
+				 * impossible.
+				 */
+				if (newtuple == NULL)
+					elog(ERROR, "Incomplete insert info.");
+
+				store_change(ctx, CHANGE_INSERT, newtuple);
+			}
+			break;
+		case REORDER_BUFFER_CHANGE_UPDATE:
+			{
+				HeapTuple	oldtuple,
+							newtuple;
+
+				oldtuple = change->data.tp.oldtuple != NULL ?
+					change->data.tp.oldtuple : NULL;
+				newtuple = change->data.tp.newtuple != NULL ?
+					change->data.tp.newtuple : NULL;
+
+				if (newtuple == NULL)
+					elog(ERROR, "Incomplete update info.");
+
+				if (oldtuple != NULL)
+					store_change(ctx, CHANGE_UPDATE_OLD, oldtuple);
+
+				store_change(ctx, CHANGE_UPDATE_NEW, newtuple);
+			}
+			break;
+		case REORDER_BUFFER_CHANGE_DELETE:
+			{
+				HeapTuple	oldtuple;
+
+				oldtuple = change->data.tp.oldtuple ?
+					change->data.tp.oldtuple : NULL;
+
+				if (oldtuple == NULL)
+					elog(ERROR, "Incomplete delete info.");
+
+				store_change(ctx, CHANGE_DELETE, oldtuple);
+			}
+			break;
+		default:
+			/* Should not come here */
+			Assert(false);
+			break;
+	}
+}
+
+/* Store concurrent data change. */
+static void
+store_change(LogicalDecodingContext *ctx, ConcurrentChangeKind kind,
+			 HeapTuple tuple)
+{
+	RepackDecodingState *dstate;
+	char	   *change_raw;
+	ConcurrentChange change;
+	bool		flattened = false;
+	Size		size;
+	Datum		values[1];
+	bool		isnull[1];
+	char	   *dst,
+			   *dst_start;
+
+	dstate = (RepackDecodingState *) ctx->output_writer_private;
+
+	size = MAXALIGN(VARHDRSZ) + SizeOfConcurrentChange;
+
+	if (tuple)
+	{
+		/*
+		 * ReorderBufferCommit() stores the TOAST chunks in its private memory
+		 * context and frees them after having called apply_change().
+		 * Therefore we need flat copy (including TOAST) that we eventually
+		 * copy into the memory context which is available to
+		 * decode_concurrent_changes().
+		 */
+		if (HeapTupleHasExternal(tuple))
+		{
+			/*
+			 * toast_flatten_tuple_to_datum() might be more convenient but we
+			 * don't want the decompression it does.
+			 */
+			tuple = toast_flatten_tuple(tuple, dstate->tupdesc);
+			flattened = true;
+		}
+
+		size += tuple->t_len;
+	}
+
+	/* XXX Isn't there any function / macro to do this? */
+	if (size >= 0x3FFFFFFF)
+		elog(ERROR, "Change is too big.");
+
+	/* Construct the change. */
+	change_raw = (char *) palloc0(size);
+	SET_VARSIZE(change_raw, size);
+
+	/*
+	 * Since the varlena alignment might not be sufficient for the structure,
+	 * set the fields in a local instance and remember where it should
+	 * eventually be copied.
+	 */
+	change.kind = kind;
+	dst_start = (char *) VARDATA(change_raw);
+
+	/*
+	 * Copy the tuple.
+	 *
+	 * CAUTION: change->tup_data.t_data must be fixed on retrieval!
+	 */
+	memcpy(&change.tup_data, tuple, sizeof(HeapTupleData));
+	dst = dst_start + SizeOfConcurrentChange;
+	memcpy(dst, tuple->t_data, tuple->t_len);
+
+	/* The data has been copied. */
+	if (flattened)
+		pfree(tuple);
+
+	/* Copy the structure so it can be stored. */
+	memcpy(dst_start, &change, SizeOfConcurrentChange);
+
+	/* Store as tuple of 1 bytea column. */
+	values[0] = PointerGetDatum(change_raw);
+	isnull[0] = false;
+	tuplestore_putvalues(dstate->tstore, dstate->tupdesc_change,
+						 values, isnull);
+
+	/* Accounting. */
+	dstate->nchanges++;
+
+	/* Cleanup. */
+	pfree(change_raw);
+}
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index cd3e43c448a..519f3953638 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -162,7 +162,7 @@ while (<$lwlocklist>)
 
 die
   "$wait_event_lwlocks[$lwlock_count] defined in wait_event_names.txt but "
-  . " missing from lwlocklist.h"
+  . "missing from lwlocklist.h"
   if $lwlock_count < scalar @wait_event_lwlocks;
 
 die
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 915d0bc9084..d0f01d85bd3 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -64,6 +64,7 @@
 #include "catalog/pg_type.h"
 #include "catalog/schemapg.h"
 #include "catalog/storage.h"
+#include "commands/cluster.h"
 #include "commands/policy.h"
 #include "commands/publicationcmds.h"
 #include "commands/trigger.h"
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 886060305f5..fbb3d66bbd9 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -214,7 +214,6 @@ static List *exportedSnapshots = NIL;
 
 /* Prototypes for local functions */
 static void UnregisterSnapshotNoOwner(Snapshot snapshot);
-static void FreeSnapshot(Snapshot snapshot);
 static void SnapshotResetXmin(void);
 
 /* ResourceOwner callbacks to track snapshot references */
@@ -659,7 +658,7 @@ CopySnapshot(Snapshot snapshot)
  * FreeSnapshot
  *		Free the memory associated with a snapshot.
  */
-static void
+void
 FreeSnapshot(Snapshot snapshot)
 {
 	Assert(snapshot->regd_count == 0);
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 626d9f1c98b..0fcf343d3af 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -5075,8 +5075,8 @@ match_previous_words(int pattern_id,
 		 * one word, so the above test is correct.
 		 */
 		if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
-			COMPLETE_WITH("ANALYZE", "VERBOSE");
-		else if (TailMatches("ANALYZE", "VERBOSE"))
+			COMPLETE_WITH("ANALYZE", "CONCURRENTLY", "VERBOSE");
+		else if (TailMatches("ANALYZE", "CONCURRENTLY", "VERBOSE"))
 			COMPLETE_WITH("ON", "OFF");
 	}
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 632c4332a8c..b0d6af0474c 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -361,14 +361,15 @@ extern void heap_multi_insert(Relation relation, TupleTableSlot **slots,
 							  BulkInsertState bistate);
 extern TM_Result heap_delete(Relation relation, const ItemPointerData *tid,
 							 CommandId cid, Snapshot crosscheck, bool wait,
-							 TM_FailureData *tmfd, bool changingPart);
+							 TM_FailureData *tmfd, bool changingPart,
+							 bool wal_logical);
 extern void heap_finish_speculative(Relation relation, const ItemPointerData *tid);
 extern void heap_abort_speculative(Relation relation, const ItemPointerData *tid);
 extern TM_Result heap_update(Relation relation, const ItemPointerData *otid,
 							 HeapTuple newtup,
 							 CommandId cid, Snapshot crosscheck, bool wait,
 							 TM_FailureData *tmfd, LockTupleMode *lockmode,
-							 TU_UpdateIndexes *update_indexes);
+							 TU_UpdateIndexes *update_indexes, bool wal_logical);
 extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
 								 CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy,
 								 bool follow_updates,
@@ -445,6 +446,10 @@ extern HTSV_Result HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer
 												   TransactionId *dead_after);
 extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
 								 uint16 infomask, TransactionId xid);
+extern bool HeapTupleMVCCInserted(HeapTuple htup, Snapshot snapshot,
+								  Buffer buffer);
+extern bool HeapTupleMVCCNotDeleted(HeapTuple htup, Snapshot snapshot,
+									Buffer buffer);
 extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
 extern bool HeapTupleIsSurelyDead(HeapTuple htup,
 								  GlobalVisState *vistest);
diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h
index 16c2b2e3c9c..2cc49fd48de 100644
--- a/src/include/access/heapam_xlog.h
+++ b/src/include/access/heapam_xlog.h
@@ -104,6 +104,8 @@
 #define XLH_DELETE_CONTAINS_OLD_KEY				(1<<2)
 #define XLH_DELETE_IS_SUPER						(1<<3)
 #define XLH_DELETE_IS_PARTITION_MOVE			(1<<4)
+/* See heap_delete() */
+#define XLH_DELETE_NO_LOGICAL					(1<<5)
 
 /* convenience macro for checking whether any form of old tuple was logged */
 #define XLH_DELETE_CONTAINS_OLD						\
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 2fa790b6bf5..d8f76d325f9 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -22,6 +22,7 @@
 #include "access/xact.h"
 #include "commands/vacuum.h"
 #include "executor/tuptable.h"
+#include "replication/logical.h"
 #include "storage/read_stream.h"
 #include "utils/rel.h"
 #include "utils/snapshot.h"
@@ -629,6 +630,8 @@ typedef struct TableAmRoutine
 											  Relation OldIndex,
 											  bool use_sort,
 											  TransactionId OldestXmin,
+											  Snapshot snapshot,
+											  LogicalDecodingContext *decoding_ctx,
 											  TransactionId *xid_cutoff,
 											  MultiXactId *multi_cutoff,
 											  double *num_tuples,
@@ -1646,6 +1649,10 @@ table_relation_copy_data(Relation rel, const RelFileLocator *newrlocator)
  *   not needed for the relation's AM
  * - *xid_cutoff - ditto
  * - *multi_cutoff - ditto
+ * - snapshot - if != NULL, ignore data changes done by transactions that this
+ *	 (MVCC) snapshot considers still in-progress or in the future.
+ * - decoding_ctx - logical decoding context, to capture concurrent data
+ *   changes.
  *
  * Output parameters:
  * - *xid_cutoff - rel's new relfrozenxid value, may be invalid
@@ -1658,6 +1665,8 @@ table_relation_copy_for_cluster(Relation OldTable, Relation NewTable,
 								Relation OldIndex,
 								bool use_sort,
 								TransactionId OldestXmin,
+								Snapshot snapshot,
+								LogicalDecodingContext *decoding_ctx,
 								TransactionId *xid_cutoff,
 								MultiXactId *multi_cutoff,
 								double *num_tuples,
@@ -1666,6 +1675,7 @@ table_relation_copy_for_cluster(Relation OldTable, Relation NewTable,
 {
 	OldTable->rd_tableam->relation_copy_for_cluster(OldTable, NewTable, OldIndex,
 													use_sort, OldestXmin,
+													snapshot, decoding_ctx,
 													xid_cutoff, multi_cutoff,
 													num_tuples, tups_vacuumed,
 													tups_recently_dead);
diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h
index 652542e8e65..b43a1740053 100644
--- a/src/include/commands/cluster.h
+++ b/src/include/commands/cluster.h
@@ -13,10 +13,15 @@
 #ifndef CLUSTER_H
 #define CLUSTER_H
 
+#include "nodes/execnodes.h"
 #include "nodes/parsenodes.h"
 #include "parser/parse_node.h"
+#include "replication/logical.h"
 #include "storage/lock.h"
+#include "storage/relfilelocator.h"
 #include "utils/relcache.h"
+#include "utils/resowner.h"
+#include "utils/tuplestore.h"
 
 
 /* flag bits for ClusterParams->options */
@@ -25,6 +30,8 @@
 #define CLUOPT_RECHECK_ISCLUSTERED 0x04 /* recheck relation state for
 										 * indisclustered */
 #define CLUOPT_ANALYZE 0x08		/* do an ANALYZE */
+#define CLUOPT_CONCURRENT 0x10	/* allow concurrent data changes */
+
 
 /* options for CLUSTER */
 typedef struct ClusterParams
@@ -33,14 +40,94 @@ typedef struct ClusterParams
 } ClusterParams;
 
 
+/*
+ * The following definitions are used by REPACK CONCURRENTLY.
+ */
+
+extern RelFileLocator repacked_rel_locator;
+extern RelFileLocator repacked_rel_toast_locator;
+
+typedef enum
+{
+	CHANGE_INSERT,
+	CHANGE_UPDATE_OLD,
+	CHANGE_UPDATE_NEW,
+	CHANGE_DELETE
+} ConcurrentChangeKind;
+
+typedef struct ConcurrentChange
+{
+	/* See the enum above. */
+	ConcurrentChangeKind kind;
+
+	/*
+	 * The actual tuple.
+	 *
+	 * The tuple data follows the ConcurrentChange structure. Before use make
+	 * sure the tuple is correctly aligned (ConcurrentChange can be stored as
+	 * bytea) and that tuple->t_data is fixed.
+	 */
+	HeapTupleData tup_data;
+} ConcurrentChange;
+
+#define SizeOfConcurrentChange (offsetof(ConcurrentChange, tup_data) + \
+								sizeof(HeapTupleData))
+
+/*
+ * Logical decoding state.
+ *
+ * Here we store the data changes that we decode from WAL while the table
+ * contents is being copied to a new storage. Also the necessary metadata
+ * needed to apply these changes to the table is stored here.
+ */
+typedef struct RepackDecodingState
+{
+	/* The relation whose changes we're decoding. */
+	Oid			relid;
+
+	/* Replication slot name. */
+	NameData	slotname;
+
+	/*
+	 * Decoded changes are stored here. Although we try to avoid excessive
+	 * batches, it can happen that the changes need to be stored to disk. The
+	 * tuplestore does this transparently.
+	 */
+	Tuplestorestate *tstore;
+
+	/* The current number of changes in tstore. */
+	double		nchanges;
+
+	/*
+	 * Descriptor to store the ConcurrentChange structure serialized (bytea).
+	 * We can't store the tuple directly because tuplestore only supports
+	 * minimum tuple and we may need to transfer OID system column from the
+	 * output plugin. Also we need to transfer the change kind, so it's better
+	 * to put everything in the structure than to use 2 tuplestores "in
+	 * parallel".
+	 */
+	TupleDesc	tupdesc_change;
+
+	/* Tuple descriptor needed to update indexes. */
+	TupleDesc	tupdesc;
+
+	/* Slot to retrieve data from tstore. */
+	TupleTableSlot *tsslot;
+
+	ResourceOwner resowner;
+} RepackDecodingState;
+
 extern void ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel);
 
 extern void cluster_rel(RepackCommand command, Relation OldHeap, Oid indexOid,
-						ClusterParams *params);
+						ClusterParams *params, bool isTopLevel);
 extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
 									   LOCKMODE lockmode);
 extern void mark_index_clustered(Relation rel, Oid indexOid, bool is_internal);
 
+extern void repack_decode_concurrent_changes(LogicalDecodingContext *ctx,
+											 XLogRecPtr end_of_wal);
+
 extern Oid	make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, Oid NewAccessMethod,
 						  char relpersistence, LOCKMODE lockmode);
 extern void finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
@@ -48,6 +135,7 @@ extern void finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
 							 bool swap_toast_by_content,
 							 bool check_constraints,
 							 bool is_internal,
+							 bool reindex,
 							 TransactionId frozenXid,
 							 MultiXactId cutoffMulti,
 							 char newrelpersistence);
diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h
index ebf004b7aa5..5024fea5e2e 100644
--- a/src/include/commands/progress.h
+++ b/src/include/commands/progress.h
@@ -69,10 +69,12 @@
 #define PROGRESS_REPACK_PHASE					1
 #define PROGRESS_REPACK_INDEX_RELID				2
 #define PROGRESS_REPACK_HEAP_TUPLES_SCANNED		3
-#define PROGRESS_REPACK_HEAP_TUPLES_WRITTEN		4
-#define PROGRESS_REPACK_TOTAL_HEAP_BLKS			5
-#define PROGRESS_REPACK_HEAP_BLKS_SCANNED		6
-#define PROGRESS_REPACK_INDEX_REBUILD_COUNT		7
+#define PROGRESS_REPACK_HEAP_TUPLES_INSERTED	4
+#define PROGRESS_REPACK_HEAP_TUPLES_UPDATED		5
+#define PROGRESS_REPACK_HEAP_TUPLES_DELETED		6
+#define PROGRESS_REPACK_TOTAL_HEAP_BLKS			7
+#define PROGRESS_REPACK_HEAP_BLKS_SCANNED		8
+#define PROGRESS_REPACK_INDEX_REBUILD_COUNT		9
 
 /*
  * Phases of repack (as advertised via PROGRESS_REPACK_PHASE).
@@ -81,9 +83,10 @@
 #define PROGRESS_REPACK_PHASE_INDEX_SCAN_HEAP	2
 #define PROGRESS_REPACK_PHASE_SORT_TUPLES		3
 #define PROGRESS_REPACK_PHASE_WRITE_NEW_HEAP	4
-#define PROGRESS_REPACK_PHASE_SWAP_REL_FILES	5
-#define PROGRESS_REPACK_PHASE_REBUILD_INDEX		6
-#define PROGRESS_REPACK_PHASE_FINAL_CLEANUP		7
+#define PROGRESS_REPACK_PHASE_CATCH_UP			5
+#define PROGRESS_REPACK_PHASE_SWAP_REL_FILES	6
+#define PROGRESS_REPACK_PHASE_REBUILD_INDEX		7
+#define PROGRESS_REPACK_PHASE_FINAL_CLEANUP		8
 
 /* Progress parameters for CREATE INDEX */
 /* 3, 4 and 5 reserved for "waitfor" metrics */
diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h
index 6d4d2d1814c..802fc4b0823 100644
--- a/src/include/replication/snapbuild.h
+++ b/src/include/replication/snapbuild.h
@@ -73,6 +73,7 @@ extern void FreeSnapshotBuilder(SnapBuild *builder);
 extern void SnapBuildSnapDecRefcount(Snapshot snap);
 
 extern Snapshot SnapBuildInitialSnapshot(SnapBuild *builder);
+extern Snapshot SnapBuildInitialSnapshotForRepack(SnapBuild *builder);
 extern Snapshot SnapBuildMVCCFromHistoric(Snapshot snapshot, bool in_place);
 extern const char *SnapBuildExportSnapshot(SnapBuild *builder);
 extern void SnapBuildClearExportedSnapshot(void);
diff --git a/src/include/storage/lockdefs.h b/src/include/storage/lockdefs.h
index 7f3ba0352f6..2739327b0da 100644
--- a/src/include/storage/lockdefs.h
+++ b/src/include/storage/lockdefs.h
@@ -36,8 +36,8 @@ typedef int LOCKMODE;
 #define AccessShareLock			1	/* SELECT */
 #define RowShareLock			2	/* SELECT FOR UPDATE/FOR SHARE */
 #define RowExclusiveLock		3	/* INSERT, UPDATE, DELETE */
-#define ShareUpdateExclusiveLock 4	/* VACUUM (non-FULL), ANALYZE, CREATE
-									 * INDEX CONCURRENTLY */
+#define ShareUpdateExclusiveLock 4	/* VACUUM (non-exclusive), ANALYZE, CREATE
+									 * INDEX CONCURRENTLY, REPACK CONCURRENTLY */
 #define ShareLock				5	/* CREATE INDEX (WITHOUT CONCURRENTLY) */
 #define ShareRowExclusiveLock	6	/* like EXCLUSIVE MODE, but allows ROW
 									 * SHARE */
diff --git a/src/include/utils/snapmgr.h b/src/include/utils/snapmgr.h
index f65f83c85cd..1f821fd2ccd 100644
--- a/src/include/utils/snapmgr.h
+++ b/src/include/utils/snapmgr.h
@@ -64,6 +64,8 @@ extern Snapshot GetLatestSnapshot(void);
 extern void SnapshotSetCommandId(CommandId curcid);
 
 extern Snapshot CopySnapshot(Snapshot snapshot);
+extern void FreeSnapshot(Snapshot snapshot);
+
 extern Snapshot GetCatalogSnapshot(Oid relid);
 extern Snapshot GetNonHistoricCatalogSnapshot(Oid relid);
 extern void InvalidateCatalogSnapshot(void);
diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile
index a618e6a9899..e477a1ba5ff 100644
--- a/src/test/modules/injection_points/Makefile
+++ b/src/test/modules/injection_points/Makefile
@@ -16,12 +16,14 @@ REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress
 
 ISOLATION = basic \
 	    inplace \
+	    repack \
 	    syscache-update-pruned \
 	    index-concurrently-upsert \
 	    index-concurrently-upsert-predicate \
 	    reindex-concurrently-upsert \
 	    reindex-concurrently-upsert-on-constraint \
 	    reindex-concurrently-upsert-partitioned
+ISOLATION_OPTS = --temp-config $(top_srcdir)/src/test/modules/injection_points/logical.conf
 
 TAP_TESTS = 1
 
diff --git a/src/test/modules/injection_points/expected/repack.out b/src/test/modules/injection_points/expected/repack.out
new file mode 100644
index 00000000000..b575e9052ee
--- /dev/null
+++ b/src/test/modules/injection_points/expected/repack.out
@@ -0,0 +1,113 @@
+Parsed test spec with 2 sessions
+
+starting permutation: wait_before_lock change_existing change_new change_subxact1 change_subxact2 check2 wakeup_before_lock check1
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step wait_before_lock: 
+	REPACK (CONCURRENTLY) repack_test USING INDEX repack_test_pkey;
+ <waiting ...>
+step change_existing: 
+	UPDATE repack_test SET i=10 where i=1;
+	UPDATE repack_test SET j=20 where i=2;
+	UPDATE repack_test SET i=30 where i=3;
+	UPDATE repack_test SET i=40 where i=30;
+	DELETE FROM repack_test WHERE i=4;
+
+step change_new: 
+	INSERT INTO repack_test(i, j) VALUES (5, 5), (6, 6), (7, 7), (8, 8);
+	UPDATE repack_test SET i=50 where i=5;
+	UPDATE repack_test SET j=60 where i=6;
+	DELETE FROM repack_test WHERE i=7;
+
+step change_subxact1: 
+	BEGIN;
+	INSERT INTO repack_test(i, j) VALUES (100, 100);
+	SAVEPOINT s1;
+	UPDATE repack_test SET i=101 where i=100;
+	SAVEPOINT s2;
+	UPDATE repack_test SET i=102 where i=101;
+	COMMIT;
+
+step change_subxact2: 
+	BEGIN;
+	SAVEPOINT s1;
+	INSERT INTO repack_test(i, j) VALUES (110, 110);
+	ROLLBACK TO SAVEPOINT s1;
+	INSERT INTO repack_test(i, j) VALUES (110, 111);
+	COMMIT;
+
+step check2: 
+	INSERT INTO relfilenodes(node)
+	SELECT relfilenode FROM pg_class WHERE relname='repack_test';
+
+	SELECT i, j FROM repack_test ORDER BY i, j;
+
+	INSERT INTO data_s2(i, j)
+	SELECT i, j FROM repack_test;
+
+  i|  j
+---+---
+  2| 20
+  6| 60
+  8|  8
+ 10|  1
+ 40|  3
+ 50|  5
+102|100
+110|111
+(8 rows)
+
+step wakeup_before_lock: 
+	SELECT injection_points_wakeup('repack-concurrently-before-lock');
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step wait_before_lock: <... completed>
+step check1: 
+	INSERT INTO relfilenodes(node)
+	SELECT relfilenode FROM pg_class WHERE relname='repack_test';
+
+	SELECT count(DISTINCT node) FROM relfilenodes;
+
+	SELECT i, j FROM repack_test ORDER BY i, j;
+
+	INSERT INTO data_s1(i, j)
+	SELECT i, j FROM repack_test;
+
+	SELECT count(*)
+	FROM data_s1 d1 FULL JOIN data_s2 d2 USING (i, j)
+	WHERE d1.i ISNULL OR d2.i ISNULL;
+
+count
+-----
+    2
+(1 row)
+
+  i|  j
+---+---
+  2| 20
+  6| 60
+  8|  8
+ 10|  1
+ 40|  3
+ 50|  5
+102|100
+110|111
+(8 rows)
+
+count
+-----
+    0
+(1 row)
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
diff --git a/src/test/modules/injection_points/logical.conf b/src/test/modules/injection_points/logical.conf
new file mode 100644
index 00000000000..c8f264bc6cb
--- /dev/null
+++ b/src/test/modules/injection_points/logical.conf
@@ -0,0 +1 @@
+wal_level = logical
\ No newline at end of file
diff --git a/src/test/modules/injection_points/meson.build b/src/test/modules/injection_points/meson.build
index 1a2af8a26c4..f8957d82afa 100644
--- a/src/test/modules/injection_points/meson.build
+++ b/src/test/modules/injection_points/meson.build
@@ -47,6 +47,7 @@ tests += {
     'specs': [
       'basic',
       'inplace',
+      'repack',
       'syscache-update-pruned',
       'index-concurrently-upsert',
       'index-concurrently-upsert-predicate',
@@ -57,6 +58,8 @@ tests += {
     'runningcheck': false, # see syscache-update-pruned
     # Some tests wait for all snapshots, so avoid parallel execution
     'runningcheck-parallel': false,
+    # 'repack' requires wal_level = 'logical'.
+    'regress_args': ['--temp-config', files('logical.conf')],
   },
   'tap': {
     'env': {
diff --git a/src/test/modules/injection_points/specs/repack.spec b/src/test/modules/injection_points/specs/repack.spec
new file mode 100644
index 00000000000..75850334986
--- /dev/null
+++ b/src/test/modules/injection_points/specs/repack.spec
@@ -0,0 +1,143 @@
+# Prefix the system columns with underscore as they are not allowed as column
+# names.
+setup
+{
+	CREATE EXTENSION injection_points;
+
+	CREATE TABLE repack_test(i int PRIMARY KEY, j int);
+	INSERT INTO repack_test(i, j) VALUES (1, 1), (2, 2), (3, 3), (4, 4);
+
+	CREATE TABLE relfilenodes(node oid);
+
+	CREATE TABLE data_s1(i int, j int);
+	CREATE TABLE data_s2(i int, j int);
+}
+
+teardown
+{
+	DROP TABLE repack_test;
+	DROP EXTENSION injection_points;
+
+	DROP TABLE relfilenodes;
+	DROP TABLE data_s1;
+	DROP TABLE data_s2;
+}
+
+session s1
+setup
+{
+	SELECT injection_points_set_local();
+	SELECT injection_points_attach('repack-concurrently-before-lock', 'wait');
+}
+# Perform the initial load and wait for s2 to do some data changes.
+step wait_before_lock
+{
+	REPACK (CONCURRENTLY) repack_test USING INDEX repack_test_pkey;
+}
+# Check the table from the perspective of s1.
+#
+# Besides the contents, we also check that relfilenode has changed.
+
+# Have each session write the contents into a table and use FULL JOIN to check
+# if the outputs are identical.
+step check1
+{
+	INSERT INTO relfilenodes(node)
+	SELECT relfilenode FROM pg_class WHERE relname='repack_test';
+
+	SELECT count(DISTINCT node) FROM relfilenodes;
+
+	SELECT i, j FROM repack_test ORDER BY i, j;
+
+	INSERT INTO data_s1(i, j)
+	SELECT i, j FROM repack_test;
+
+	SELECT count(*)
+	FROM data_s1 d1 FULL JOIN data_s2 d2 USING (i, j)
+	WHERE d1.i ISNULL OR d2.i ISNULL;
+}
+teardown
+{
+    SELECT injection_points_detach('repack-concurrently-before-lock');
+}
+
+session s2
+# Change the existing data. UPDATE changes both key and non-key columns. Also
+# update one row twice to test whether tuple version generated by this session
+# can be found.
+step change_existing
+{
+	UPDATE repack_test SET i=10 where i=1;
+	UPDATE repack_test SET j=20 where i=2;
+	UPDATE repack_test SET i=30 where i=3;
+	UPDATE repack_test SET i=40 where i=30;
+	DELETE FROM repack_test WHERE i=4;
+}
+# Insert new rows and UPDATE / DELETE some of them. Again, update both key and
+# non-key column.
+step change_new
+{
+	INSERT INTO repack_test(i, j) VALUES (5, 5), (6, 6), (7, 7), (8, 8);
+	UPDATE repack_test SET i=50 where i=5;
+	UPDATE repack_test SET j=60 where i=6;
+	DELETE FROM repack_test WHERE i=7;
+}
+
+# When applying concurrent data changes, we should see the effects of an
+# in-progress subtransaction.
+#
+# XXX Not sure this test is useful now - it was designed for the patch that
+# preserves tuple visibility and which therefore modifies
+# TransactionIdIsCurrentTransactionId().
+step change_subxact1
+{
+	BEGIN;
+	INSERT INTO repack_test(i, j) VALUES (100, 100);
+	SAVEPOINT s1;
+	UPDATE repack_test SET i=101 where i=100;
+	SAVEPOINT s2;
+	UPDATE repack_test SET i=102 where i=101;
+	COMMIT;
+}
+
+# When applying concurrent data changes, we should not see the effects of a
+# rolled back subtransaction.
+#
+# XXX Is this test useful? See above.
+step change_subxact2
+{
+	BEGIN;
+	SAVEPOINT s1;
+	INSERT INTO repack_test(i, j) VALUES (110, 110);
+	ROLLBACK TO SAVEPOINT s1;
+	INSERT INTO repack_test(i, j) VALUES (110, 111);
+	COMMIT;
+}
+
+# Check the table from the perspective of s2.
+step check2
+{
+	INSERT INTO relfilenodes(node)
+	SELECT relfilenode FROM pg_class WHERE relname='repack_test';
+
+	SELECT i, j FROM repack_test ORDER BY i, j;
+
+	INSERT INTO data_s2(i, j)
+	SELECT i, j FROM repack_test;
+}
+step wakeup_before_lock
+{
+	SELECT injection_points_wakeup('repack-concurrently-before-lock');
+}
+
+# Test if data changes introduced while one session is performing REPACK
+# CONCURRENTLY find their way into the table.
+permutation
+	wait_before_lock
+	change_existing
+	change_new
+	change_subxact1
+	change_subxact2
+	check2
+	wakeup_before_lock
+	check1
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 1c957f12d27..e23751afeaf 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2007,7 +2007,7 @@ pg_stat_progress_cluster| SELECT pid,
     phase,
     repack_index_relid AS cluster_index_relid,
     heap_tuples_scanned,
-    heap_tuples_written,
+    (heap_tuples_inserted + heap_tuples_updated) AS heap_tuples_written,
     heap_blks_total,
     heap_blks_scanned,
     index_rebuild_count
@@ -2087,17 +2087,20 @@ pg_stat_progress_repack| SELECT s.pid,
             WHEN 2 THEN 'index scanning heap'::text
             WHEN 3 THEN 'sorting tuples'::text
             WHEN 4 THEN 'writing new heap'::text
-            WHEN 5 THEN 'swapping relation files'::text
-            WHEN 6 THEN 'rebuilding index'::text
-            WHEN 7 THEN 'performing final cleanup'::text
+            WHEN 5 THEN 'catch-up'::text
+            WHEN 6 THEN 'swapping relation files'::text
+            WHEN 7 THEN 'rebuilding index'::text
+            WHEN 8 THEN 'performing final cleanup'::text
             ELSE NULL::text
         END AS phase,
     (s.param3)::oid AS repack_index_relid,
     s.param4 AS heap_tuples_scanned,
-    s.param5 AS heap_tuples_written,
-    s.param6 AS heap_blks_total,
-    s.param7 AS heap_blks_scanned,
-    s.param8 AS index_rebuild_count
+    s.param5 AS heap_tuples_inserted,
+    s.param6 AS heap_tuples_updated,
+    s.param7 AS heap_tuples_deleted,
+    s.param8 AS heap_blks_total,
+    s.param9 AS heap_blks_scanned,
+    s.param10 AS index_rebuild_count
    FROM (pg_stat_get_progress_info('REPACK'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_progress_vacuum| SELECT s.pid,
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 4641da9b746..5e546160a2f 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -411,6 +411,7 @@ CatCacheHeader
 CatalogId
 CatalogIdMapEntry
 CatalogIndexState
+ChangeDest
 ChangeVarNodes_callback
 ChangeVarNodes_context
 CheckPoint
@@ -487,6 +488,8 @@ CompressFileHandle
 CompressionLocation
 CompressorState
 ComputeXidHorizonsResult
+ConcurrentChange
+ConcurrentChangeKind
 ConditionVariable
 ConditionVariableMinimallyPadded
 ConditionalStack
@@ -1264,6 +1267,7 @@ IndexElem
 IndexFetchHeapData
 IndexFetchTableData
 IndexInfo
+IndexInsertState
 IndexList
 IndexOnlyScan
 IndexOnlyScanState
@@ -2556,6 +2560,7 @@ ReorderBufferUpdateProgressTxnCB
 ReorderTuple
 RepOriginId
 RepackCommand
+RepackDecodingState
 RepackStmt
 ReparameterizeForeignPathByChild_function
 ReplaceVarsFromTargetList_context
-- 
2.47.3


--=-=-=--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* [PATCH 2/2] Apply the same technique to PrintNewControlValues too
@ 2026-01-31 15:01  Álvaro Herrera <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Álvaro Herrera @ 2026-01-31 15:01 UTC (permalink / raw)

---
 src/bin/pg_resetwal/entries.h     |  60 +++++++--------
 src/bin/pg_resetwal/pg_resetwal.c | 121 ++++++++++++++++++++----------
 2 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/src/bin/pg_resetwal/entries.h b/src/bin/pg_resetwal/entries.h
index 6b7686da83a..25f2c49b3a8 100644
--- a/src/bin/pg_resetwal/entries.h
+++ b/src/bin/pg_resetwal/entries.h
@@ -1,62 +1,62 @@
-CONTROLDATA_LINE("pg_control version number",
+CONTROLDATA_LINE(CD_CONTROL_VERSION, "pg_control version number",
 				 "%u", ControlFile.pg_control_version)
-CONTROLDATA_LINE("Catalog version number",
+CONTROLDATA_LINE(CD_CATALOG_VERSION, "Catalog version number",
 				 "%u", ControlFile.catalog_version_no)
-CONTROLDATA_LINE("Database system identifier",
+CONTROLDATA_LINE(CD_SYSTEM_IDENTIFIER, "Database system identifier",
 				 "%" PRIu64, ControlFile.system_identifier)
-CONTROLDATA_LINE("Latest checkpoint's TimeLineID",
+CONTROLDATA_LINE(CD_CKPT_TIMELINE, "Latest checkpoint's TimeLineID",
 				 "%u", ControlFile.checkPointCopy.ThisTimeLineID)
-CONTROLDATA_LINE("Latest checkpoint's full_page_writes",
+CONTROLDATA_LINE(CD_CKPT_FPW, "Latest checkpoint's full_page_writes",
 				 "%s", (ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")))
-CONTROLDATA_LINE("Latest checkpoint's NextXID",
+CONTROLDATA_LINE(CD_CKPT_NEXTXID, "Latest checkpoint's NextXID",
 				 "%u:%u", EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid), XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid))
-CONTROLDATA_LINE("Latest checkpoint's NextOID",
+CONTROLDATA_LINE(CD_CKPT_NEXTOID, "Latest checkpoint's NextOID",
 				 "%u", ControlFile.checkPointCopy.nextOid)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiXactId",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXID, "Latest checkpoint's NextMultiXactId",
 				 "%u", ControlFile.checkPointCopy.nextMulti)
-CONTROLDATA_LINE("Latest checkpoint's NextMultiOffset",
+CONTROLDATA_LINE(CD_CKPT_NEXTMXOFF, "Latest checkpoint's NextMultiOffset",
 				 "%" PRIu64, ControlFile.checkPointCopy.nextMultiOffset)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID, "Latest checkpoint's oldestXID",
 				 "%u", ControlFile.checkPointCopy.oldestXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestXID's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDESTXID_DB, "Latest checkpoint's oldestXID's DB",
 				 "%u", ControlFile.checkPointCopy.oldestXidDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestActiveXID",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_ACTIVEXID, "Latest checkpoint's oldestActiveXID",
 				 "%u", ControlFile.checkPointCopy.oldestActiveXid)
-CONTROLDATA_LINE("Latest checkpoint's oldestMultiXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI, "Latest checkpoint's oldestMultiXid",
 				 "%u", ControlFile.checkPointCopy.oldestMulti)
-CONTROLDATA_LINE("Latest checkpoint's oldestMulti's DB",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_MULTI_DB, "Latest checkpoint's oldestMulti's DB",
 				 "%u", ControlFile.checkPointCopy.oldestMultiDB)
-CONTROLDATA_LINE("Latest checkpoint's oldestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_OLDEST_COMMITTS_XID, "Latest checkpoint's oldestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.oldestCommitTsXid)
-CONTROLDATA_LINE("Latest checkpoint's newestCommitTsXid",
+CONTROLDATA_LINE(CD_CKPT_NEWEST_COMMITTS_XID, "Latest checkpoint's newestCommitTsXid",
 				 "%u", ControlFile.checkPointCopy.newestCommitTsXid)
-CONTROLDATA_LINE("Maximum data alignment",
+CONTROLDATA_LINE(CD_MAXALIGN, "Maximum data alignment",
 				 "%u", ControlFile.maxAlign)
-CONTROLDATA_LINE("Database block size",
+CONTROLDATA_LINE(CD_BLCKSZ, "Database block size",
 				 "%u", ControlFile.blcksz)
-CONTROLDATA_LINE("Blocks per segment of large relation",
+CONTROLDATA_LINE(CD_RELSEG_SZ, "Blocks per segment of large relation",
 				 "%u", ControlFile.relseg_size)
-CONTROLDATA_LINE("Pages per SLRU segment",
+CONTROLDATA_LINE(CD_SLRU_PPS, "Pages per SLRU segment",
 				 "%u", ControlFile.slru_pages_per_segment)
-CONTROLDATA_LINE("WAL block size",
+CONTROLDATA_LINE(CD_WAL_BLCKSZ, "WAL block size",
 				 "%u", ControlFile.xlog_blcksz)
-CONTROLDATA_LINE("Bytes per WAL segment",
+CONTROLDATA_LINE(CD_WAL_SEGSIZE, "Bytes per WAL segment",
 				 "%u", ControlFile.xlog_seg_size)
-CONTROLDATA_LINE("Maximum length of identifiers",
+CONTROLDATA_LINE(CD_WAL_NAMEDATALEN, "Maximum length of identifiers",
 				 "%u", ControlFile.nameDataLen)
-CONTROLDATA_LINE("Maximum columns in an index",
+CONTROLDATA_LINE(CD_INDEX_MAX_KEYS, "Maximum columns in an index",
 				 "%u", ControlFile.indexMaxKeys)
-CONTROLDATA_LINE("Maximum size of a TOAST chunk",
+CONTROLDATA_LINE(CD_TOAST_MAXCHUNKSZ, "Maximum size of a TOAST chunk",
 				 "%u", ControlFile.toast_max_chunk_size)
-CONTROLDATA_LINE("Size of a large-object chunk",
+CONTROLDATA_LINE(CD_LO_BLKSZ, "Size of a large-object chunk",
 				 "%u", ControlFile.loblksize)
 
 /* This is no longer configurable, but users may still expect to see it: */
-CONTROLDATA_LINE("Date/time type storage",
+CONTROLDATA_LINE(CD_DATETIME_INT64, "Date/time type storage",
 				 "%s", _("64-bit integers"))
-CONTROLDATA_LINE("Float8 argument passing",
+CONTROLDATA_LINE(CD_FLOAT8_ARGS, "Float8 argument passing",
 				 "%s", ControlFile.float8ByVal ? _("by value") : _("by reference"))
-CONTROLDATA_LINE("Data page checksum version",
+CONTROLDATA_LINE(CD_CHECKSUMS, "Data page checksum version",
 				 "%u", ControlFile.data_checksum_version)
-CONTROLDATA_LINE("Default char data signedness",
+CONTROLDATA_LINE(CD_CHAR_SIGNEDNESS, "Default char data signedness",
 				 "%s", ControlFile.default_char_signedness ? _("signed") : _("unsigned"))
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index fb17b6f80e0..23bf1c62183 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -55,6 +55,7 @@
 #include "common/restricted_token.h"
 #include "common/string.h"
 #include "fe_utils/option_utils.h"
+#include "fe_utils/simple_list.h"
 #include "fe_utils/version.h"
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
@@ -119,6 +120,14 @@ static int	internal_wcswidth(const char *pwcs, size_t len, int encoding);
 static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
 static uint64 strtouint64_strict(const char *restrict s, char **restrict endptr, int base);
 
+/* Define the string enums */
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	symbol,
+enum ControldataStrings {
+#include "entries.h"
+};
+#undef CONTROLDATA_LINE
+
 
 int
 main(int argc, char *argv[])
@@ -768,7 +777,7 @@ PrintControlValues(bool guessed)
 	 * First, determine the maximum length of the description of all entries,
 	 * some or all of which might be translated.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	thislen = internal_wcswidth(_(description),			\
 								strlen(_(description)),	\
 								encoding);				\
@@ -781,7 +790,7 @@ PrintControlValues(bool guessed)
 	 * Print each line: the possibly-translated description, then some padding
 	 * spaces according to its display width, then the value.
 	 */
-#define CONTROLDATA_LINE(description, fmt, ...)			\
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
 	{													\
 		int		thisstrlen;								\
 														\
@@ -807,69 +816,99 @@ static void
 PrintNewControlValues(void)
 {
 	char		fname[MAXFNAMELEN];
+	int			encoding = pg_get_encoding_from_locale(NULL, true);
+	SimpleOidList	toprint = {NULL, NULL};
+	int			maxlen = 0;
+	int			thislen;
 
 	/* This will be always printed in order to keep format same. */
 	printf(_("\n\nValues to be changed:\n\n"));
 
-	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
-				 newXlogSegNo, WalSegSz);
-	printf(_("First log segment after reset:        %s\n"), fname);
-
 	if (mxids_given)
 	{
-		printf(_("NextMultiXactId:                      %u\n"),
-			   ControlFile.checkPointCopy.nextMulti);
-		printf(_("OldestMultiXid:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestMulti);
-		printf(_("OldestMulti's DB:                     %u\n"),
-			   ControlFile.checkPointCopy.oldestMultiDB);
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_MULTI_DB);
 	}
 
 	if (next_mxoff_given)
-	{
-		printf(_("NextMultiOffset:                      %" PRIu64 "\n"),
-			   ControlFile.checkPointCopy.nextMultiOffset);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTMXOFF);
 
 	if (next_oid_given)
-	{
-		printf(_("NextOID:                              %u\n"),
-			   ControlFile.checkPointCopy.nextOid);
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTOID);
 
 	if (next_xid_given)
-	{
-		printf(_("NextXID:                              %u\n"),
-			   XidFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
-	}
+		simple_oid_list_append(&toprint, CD_CKPT_NEXTXID);
 
 	if (oldest_xid_given)
 	{
-		printf(_("OldestXID:                            %u\n"),
-			   ControlFile.checkPointCopy.oldestXid);
-		printf(_("OldestXID's DB:                       %u\n"),
-			   ControlFile.checkPointCopy.oldestXidDB);
-	}
-
-	if (next_xid_epoch_given)
-	{
-		printf(_("NextXID epoch:                        %u\n"),
-			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDESTXID_DB);
 	}
 
 	if (commit_ts_xids_given)
 	{
-		printf(_("oldestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.oldestCommitTsXid);
-		printf(_("newestCommitTsXid:                    %u\n"),
-			   ControlFile.checkPointCopy.newestCommitTsXid);
+		simple_oid_list_append(&toprint, CD_CKPT_OLDEST_COMMITTS_XID);
+		simple_oid_list_append(&toprint, CD_CKPT_NEWEST_COMMITTS_XID);
 	}
 
 	if (wal_segsize_given)
-	{
-		printf(_("Bytes per WAL segment:                %u\n"),
-			   ControlFile.xlog_seg_size);
+		simple_oid_list_append(&toprint, CD_WAL_SEGSIZE);
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{															\
+	thislen = internal_wcswidth(_(description),					\
+								strlen(_(description)),			\
+								encoding);						\
+	if (thislen > maxlen)										\
+		maxlen = thislen;										\
 	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
+
+
+	XLogFileName(fname, ControlFile.checkPointCopy.ThisTimeLineID,
+				 newXlogSegNo, WalSegSz);
+
+	/* We print this one inconditionally */
+	{
+		char *str = "First log segment after reset";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%s\n", _(str), maxlen - thislen + 2, " ", fname);
+	}
+
+	/* We print the XID epoch in a degenerate case */
+	if (next_xid_epoch_given)
+	{
+		char *str = "NextXID epoch";
+		thislen = internal_wcswidth(_(str), strlen(_(str)), encoding);
+		if (thislen > maxlen)
+			maxlen = thislen;
+		printf("%s:%*s%u\n", _(str), maxlen - thislen + 2, " ",
+			   EpochFromFullTransactionId(ControlFile.checkPointCopy.nextXid));
+
+	}
+
+#define CONTROLDATA_LINE(symbol, description, fmt, ...)			\
+	if (simple_oid_list_member(&toprint, symbol))				\
+	{													\
+		int		thisstrlen;								\
+														\
+		thisstrlen = strlen(_(description));			\
+		thislen = internal_wcswidth(_(description),		\
+									thisstrlen,			\
+									encoding);			\
+		printf("%s:%*s" fmt "\n",						\
+			   _(description),							\
+			   maxlen - thislen + 2,					\
+			   " ",										\
+			   __VA_ARGS__);							\
+	}
+#include "entries.h"
+#undef CONTROLDATA_LINE
 }
 
 
-- 
2.47.3


--m4rixdodkhrlzpzv--





^ permalink  raw  reply  [nested|flat] 180+ messages in thread

* Add heap and index vacuum timings to pg_stat_progress_vacuum
@ 2026-05-04 05:41  Bharath Rupireddy <[email protected]>
  0 siblings, 0 replies; 180+ messages in thread

From: Bharath Rupireddy @ 2026-05-04 05:41 UTC (permalink / raw)
  To: PostgreSQL Hackers <[email protected]>

Hi,

When vacuum is running for hours on a table with many indexes, we can see
what phase it is in and how many index vacuum cycles have happened
(index_vacuum_count), but not how much time each phase has taken. That
makes it hard to tell what is actually slow.

The attached patch adds three columns to pg_stat_progress_vacuum that
report the total time spent in heap vacuuming, index vacuuming, and index
cleanup. The values are accumulated across overflow cycles when the dead
TID store fills up.

These columns make it easy to see whether the bottleneck is heap scanning
or index processing, analyze why vacuum is slow, and adjust
maintenance_work_mem accordingly to reduce TID store overflow cycles. They
also make it possible to estimate how long
vacuum takes to finish - polling these timing columns along with scanned
blocks gives a good estimated time.

We could put this behind a track_vacuum_timing GUC similar to
track_io_timing and track_wal_timing of the time capturing calls
seem costly. I'd prefer not to add another GUC, but I'm open to thoughts on
this.

For example, I tested with a 3M-row table (3.9 GB), 4 btree indexes, and
maintenance_work_mem=256kB (kept low to force TID-store overflows). About
34 minutes in, only 13% through the vacuum [1]. index_vacuum_time is 2006s
vs heap_vacuum_time of 2.1s - index processing is where all the time goes.
13,188 overflow cycles × 4 indexes = 52,752 index scans so far. In
production, tables with more indexes, these columns show exactly where
vacuum time is going and whether raising maintenance_work_mem would help.

With the help of the attached sql function, the estimated time to finish
the vacuum is about 3.5 hours [2].

Thoughts?

[1]
  SELECT * FROM pg_stat_progress_vacuum;
   pid                  | 18764
   relid                | 16384
   phase                | vacuuming indexes
   heap_blks_total      | 500000
   heap_blks_scanned    | 66202
   heap_blks_vacuumed   | 66202
   index_vacuum_count   | 13188
   max_dead_tuple_bytes | 262144
   dead_tuple_bytes     | 0
   num_dead_item_ids    | 0
   indexes_total        | 4
   indexes_processed    | 4
   delay_time           | 0
   mode                 | manual
   started_by           | user
   heap_vacuum_time     | 2.098345
   index_vacuum_time    | 2005.931383
   index_cleanup_time   | 0

[2]
  SELECT * FROM estimate_vacuum_completion();
   pid            | 18764
   relname        | vac_timing_test
   pct_done       | 13.24
   time_remaining | 03:35:39


-- 
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com


Attachments:

  [application/x-patch] v1-0001-Add-heap-and-index-vacuum-timings-to-pg_stat_prog.patch (12.5K, ../../CALj2ACVD08XgDcQpTSegKDiyJHwJ6eK89X+1WksWqUJxT86A_A@mail.gmail.com/3-v1-0001-Add-heap-and-index-vacuum-timings-to-pg_stat_prog.patch)
  download | inline diff:
From b266993a0d61c3f46da32730086b7d538150f4fb Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <[email protected]>
Date: Sun, 19 Apr 2026 00:01:13 +0000
Subject: [PATCH v1] Add heap and index vacuum timings to
 pg_stat_progress_vacuum

When vacuum is running for hours on a table with many indexes,
we can see what phase it is in and how many index vacuum cycles
have happened (index_vacuum_count), but not how much time each
phase has taken. That makes it hard to tell what is actually
slow.

This commit adds three columns to pg_stat_progress_vacuum that
report the total time spent in heap vacuuming, index vacuuming,
and index cleanup. The values carry over across overflow cycles
when the dead TID store fills up and vacuum restarts.

These columns make it easy to see whether the bottleneck is heap
scanning or index processing, analyze why vacuum is slow, and
adjust maintenance_work_mem accordingly to reduce TID store
overflow cycles.

These columns also make it possible to estimate how long vacuum
takes to finish. Polling these timing columns along with scanned
blocks gives a good estimated time to finish vacuum.
---
 doc/src/sgml/monitoring.sgml         | 36 +++++++++++++++
 src/backend/access/heap/vacuumlazy.c | 68 ++++++++++++++++++++++++++++
 src/backend/catalog/system_views.sql |  5 +-
 src/include/commands/progress.h      |  3 ++
 src/test/regress/expected/rules.out  |  5 +-
 5 files changed, 115 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 08d5b824552..7912b9fce7f 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -7577,6 +7577,42 @@ FROM pg_stat_get_backend_idset() AS backendid;
        </itemizedlist>
       </para></entry>
      </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>heap_vacuum_time</structfield> <type>double precision</type>
+      </para>
+      <para>
+       Total time spent in heap vacuuming phase, in seconds (see
+       <xref linkend="vacuum-phases"/>). This includes time spent scanning
+       the heap to collect dead TIDs, plus the time spent in the heap
+       vacuuming pass (removing dead items from heap pages). The time is
+       accumulated across multiple passes when the TID store fills up.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>index_vacuum_time</structfield> <type>double precision</type>
+      </para>
+      <para>
+       Total time spent in the index vacuuming phase, in seconds (see
+       <xref linkend="vacuum-phases"/>). This includes the time to vacuum
+       all indexes on the table in each pass, and is accumulated across
+       multiple passes when all indexes have to be vacuumed again.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>index_cleanup_time</structfield> <type>double precision</type>
+      </para>
+      <para>
+       Total time spent in the index cleanup phase, in seconds (see
+       <xref linkend="vacuum-phases"/>). This includes the time to
+       clean up all indexes on the table.
+      </para></entry>
+     </row>
     </tbody>
    </tgroup>
   </table>
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 39395aed0d5..bdcf424e42c 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -345,6 +345,12 @@ typedef struct LVRelState
 	int			num_dead_items_resets;
 	Size		total_dead_items_bytes;
 
+	/* Per-phase elapsed time tracking (in microseconds) */
+	instr_time	phase_start_time;	/* when the current phase started */
+	int64		heap_vacuum_elapsed_us;
+	int64		index_vacuum_elapsed_us;
+	int64		index_cleanup_elapsed_us;
+
 	/*
 	 * Total number of planned and actually launched parallel workers for
 	 * index vacuuming and index cleanup.
@@ -767,6 +773,9 @@ heap_vacuum_rel(Relation rel, const VacuumParams *params,
 	vacrel->num_index_scans = 0;
 	vacrel->num_dead_items_resets = 0;
 	vacrel->total_dead_items_bytes = 0;
+	vacrel->heap_vacuum_elapsed_us = 0;
+	vacrel->index_vacuum_elapsed_us = 0;
+	vacrel->index_cleanup_elapsed_us = 0;
 	vacrel->tuples_deleted = 0;
 	vacrel->tuples_frozen = 0;
 	vacrel->lpdead_items = 0;
@@ -1285,6 +1294,7 @@ lazy_scan_heap(LVRelState *vacrel)
 	BlockNumber orig_eager_scan_success_limit =
 		vacrel->eager_scan_remaining_successes; /* for logging */
 	Buffer		vmbuffer = InvalidBuffer;
+	instr_time	now;
 	const int	initprog_index[] = {
 		PROGRESS_VACUUM_PHASE,
 		PROGRESS_VACUUM_TOTAL_HEAP_BLKS,
@@ -1298,6 +1308,9 @@ lazy_scan_heap(LVRelState *vacrel)
 	initprog_val[2] = vacrel->dead_items_info->max_bytes;
 	pgstat_progress_update_multi_param(3, initprog_index, initprog_val);
 
+	/* Start timing the heap scan phase */
+	INSTR_TIME_SET_CURRENT(vacrel->phase_start_time);
+
 	/* Initialize for the first heap_vac_scan_next_block() call */
 	vacrel->current_block = InvalidBlockNumber;
 	vacrel->next_unskippable_block = InvalidBlockNumber;
@@ -1367,6 +1380,15 @@ lazy_scan_heap(LVRelState *vacrel)
 				vmbuffer = InvalidBuffer;
 			}
 
+			/*
+			 * Accumulate heap vacuum time before switching to index vacuum.
+			 */
+			INSTR_TIME_SET_CURRENT(now);
+			INSTR_TIME_SUBTRACT(now, vacrel->phase_start_time);
+			vacrel->heap_vacuum_elapsed_us += INSTR_TIME_GET_MICROSEC(now);
+			pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_VACUUM_TIME,
+										 vacrel->heap_vacuum_elapsed_us);
+
 			/* Perform a round of index and heap vacuuming */
 			vacrel->consider_bypass_optimization = false;
 			lazy_vacuum(vacrel);
@@ -1383,6 +1405,9 @@ lazy_scan_heap(LVRelState *vacrel)
 			/* Report that we are once again scanning the heap */
 			pgstat_progress_update_param(PROGRESS_VACUUM_PHASE,
 										 PROGRESS_VACUUM_PHASE_SCAN_HEAP);
+
+			/* Restart heap scan timing */
+			INSTR_TIME_SET_CURRENT(vacrel->phase_start_time);
 		}
 
 		buf = read_stream_next_buffer(stream, &per_buffer_data);
@@ -1596,6 +1621,15 @@ lazy_scan_heap(LVRelState *vacrel)
 
 	read_stream_end(stream);
 
+	/*
+	 * Accumulate final heap vacuum time before index vacuuming.
+	 */
+	INSTR_TIME_SET_CURRENT(now);
+	INSTR_TIME_SUBTRACT(now, vacrel->phase_start_time);
+	vacrel->heap_vacuum_elapsed_us += INSTR_TIME_GET_MICROSEC(now);
+	pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_VACUUM_TIME,
+								 vacrel->heap_vacuum_elapsed_us);
+
 	/*
 	 * Do index vacuuming (call each index's ambulkdelete routine), then do
 	 * related heap vacuuming
@@ -2506,6 +2540,7 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
 	};
 	int64		progress_start_val[2];
 	int64		progress_end_val[3];
+	instr_time	now;
 
 	Assert(vacrel->nindexes > 0);
 	Assert(vacrel->do_index_vacuuming);
@@ -2526,6 +2561,9 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
 	progress_start_val[1] = vacrel->nindexes;
 	pgstat_progress_update_multi_param(2, progress_start_index, progress_start_val);
 
+	/* Start timing index vacuum phase */
+	INSTR_TIME_SET_CURRENT(vacrel->phase_start_time);
+
 	if (!ParallelVacuumIsActive(vacrel))
 	{
 		for (int idx = 0; idx < vacrel->nindexes; idx++)
@@ -2582,6 +2620,14 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
 	 * We deliberately include the case where we started a round of bulk
 	 * deletes that we weren't able to finish due to the failsafe triggering.
 	 */
+
+	/* Accumulate index vacuum elapsed time */
+	INSTR_TIME_SET_CURRENT(now);
+	INSTR_TIME_SUBTRACT(now, vacrel->phase_start_time);
+	vacrel->index_vacuum_elapsed_us += INSTR_TIME_GET_MICROSEC(now);
+	pgstat_progress_update_param(PROGRESS_VACUUM_INDEX_VACUUM_TIME,
+								 vacrel->index_vacuum_elapsed_us);
+
 	vacrel->num_index_scans++;
 	progress_end_val[0] = 0;
 	progress_end_val[1] = 0;
@@ -2644,6 +2690,7 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
 	Buffer		vmbuffer = InvalidBuffer;
 	LVSavedErrInfo saved_err_info;
 	TidStoreIter *iter;
+	instr_time	now;
 
 	Assert(vacrel->do_index_vacuuming);
 	Assert(vacrel->do_index_cleanup);
@@ -2653,6 +2700,9 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
 	pgstat_progress_update_param(PROGRESS_VACUUM_PHASE,
 								 PROGRESS_VACUUM_PHASE_VACUUM_HEAP);
 
+	/* Start timing heap vacuum (second pass) phase */
+	INSTR_TIME_SET_CURRENT(vacrel->phase_start_time);
+
 	/* Update error traceback information */
 	update_vacuum_error_info(vacrel, &saved_err_info,
 							 VACUUM_ERRCB_PHASE_VACUUM_HEAP,
@@ -2742,6 +2792,13 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
 					vacrel->relname, vacrel->dead_items_info->num_items,
 					vacuumed_pages)));
 
+	/* Accumulate heap vacuum (second pass) elapsed time */
+	INSTR_TIME_SET_CURRENT(now);
+	INSTR_TIME_SUBTRACT(now, vacrel->phase_start_time);
+	vacrel->heap_vacuum_elapsed_us += INSTR_TIME_GET_MICROSEC(now);
+	pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_VACUUM_TIME,
+								 vacrel->heap_vacuum_elapsed_us);
+
 	/* Revert to the previous phase information for error traceback */
 	restore_vacuum_error_info(vacrel, &saved_err_info);
 }
@@ -2955,6 +3012,7 @@ lazy_cleanup_all_indexes(LVRelState *vacrel)
 	};
 	int64		progress_start_val[2];
 	int64		progress_end_val[2] = {0, 0};
+	instr_time	now;
 
 	Assert(vacrel->do_index_cleanup);
 	Assert(vacrel->nindexes > 0);
@@ -2967,6 +3025,9 @@ lazy_cleanup_all_indexes(LVRelState *vacrel)
 	progress_start_val[1] = vacrel->nindexes;
 	pgstat_progress_update_multi_param(2, progress_start_index, progress_start_val);
 
+	/* Start timing index cleanup phase */
+	INSTR_TIME_SET_CURRENT(vacrel->phase_start_time);
+
 	if (!ParallelVacuumIsActive(vacrel))
 	{
 		for (int idx = 0; idx < vacrel->nindexes; idx++)
@@ -2992,6 +3053,13 @@ lazy_cleanup_all_indexes(LVRelState *vacrel)
 											&(vacrel->worker_usage.cleanup));
 	}
 
+	/* Accumulate index cleanup elapsed time */
+	INSTR_TIME_SET_CURRENT(now);
+	INSTR_TIME_SUBTRACT(now, vacrel->phase_start_time);
+	vacrel->index_cleanup_elapsed_us += INSTR_TIME_GET_MICROSEC(now);
+	pgstat_progress_update_param(PROGRESS_VACUUM_INDEX_CLEANUP_TIME,
+								 vacrel->index_cleanup_elapsed_us);
+
 	/* Reset the progress counters */
 	pgstat_progress_update_multi_param(2, progress_end_index, progress_end_val);
 }
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 73a1c1c4670..50c827ae390 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1342,7 +1342,10 @@ CREATE VIEW pg_stat_progress_vacuum AS
         CASE S.param13 WHEN 1 THEN 'manual'
                        WHEN 2 THEN 'autovacuum'
                        WHEN 3 THEN 'autovacuum_wraparound'
-                       ELSE NULL END AS started_by
+                       ELSE NULL END AS started_by,
+        S.param14 / 1000000::double precision AS heap_vacuum_time,
+        S.param15 / 1000000::double precision AS index_vacuum_time,
+        S.param16 / 1000000::double precision AS index_cleanup_time
     FROM pg_stat_get_progress_info('VACUUM') AS S
         LEFT JOIN pg_database D ON S.datid = D.oid;
 
diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h
index 2a12920c75f..dc4abc11647 100644
--- a/src/include/commands/progress.h
+++ b/src/include/commands/progress.h
@@ -31,6 +31,9 @@
 #define PROGRESS_VACUUM_DELAY_TIME				10
 #define PROGRESS_VACUUM_MODE					11
 #define PROGRESS_VACUUM_STARTED_BY				12
+#define PROGRESS_VACUUM_HEAP_VACUUM_TIME		13
+#define PROGRESS_VACUUM_INDEX_VACUUM_TIME		14
+#define PROGRESS_VACUUM_INDEX_CLEANUP_TIME		15
 
 /* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */
 #define PROGRESS_VACUUM_PHASE_SCAN_HEAP			1
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index a65a5bf0c4f..7242b929815 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2202,7 +2202,10 @@ pg_stat_progress_vacuum| SELECT s.pid,
             WHEN 2 THEN 'autovacuum'::text
             WHEN 3 THEN 'autovacuum_wraparound'::text
             ELSE NULL::text
-        END AS started_by
+        END AS started_by,
+    ((s.param14)::double precision / (1000000)::double precision) AS heap_vacuum_time,
+    ((s.param15)::double precision / (1000000)::double precision) AS index_vacuum_time,
+    ((s.param16)::double precision / (1000000)::double precision) AS index_cleanup_time
    FROM (pg_stat_get_progress_info('VACUUM'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_recovery| SELECT promote_triggered,
-- 
2.47.3



  [application/sql] estimate_vacuum_completion.sql (1.3K, ../../CALj2ACVD08XgDcQpTSegKDiyJHwJ6eK89X+1WksWqUJxT86A_A@mail.gmail.com/4-estimate_vacuum_completion.sql)
  download

^ permalink  raw  reply  [nested|flat] 180+ messages in thread


end of thread, other threads:[~2026-05-04 05:41 UTC | newest]

Thread overview: 180+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2019-07-15 00:00 [PATCH 3/5] Fix handling of NULLs in MCV items and constants Tomas Vondra <[email protected]>
2023-08-14 10:59 [PATCH] Track DEALLOCATE statements in pg_stat_activity Dagfinn Ilmari Mannsåker <[email protected]>
2023-08-14 10:59 [PATCH] Track DEALLOCATE statements in pg_stat_activity Dagfinn Ilmari Mannsåker <[email protected]>
2025-12-04 17:20 [PATCH 4/4] Add CONCURRENTLY option to REPACK command. Antonin Houska <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-01-31 15:01 [PATCH 2/2] Apply the same technique to PrintNewControlValues too Álvaro Herrera <[email protected]>
2026-05-04 05:41 Add heap and index vacuum timings to pg_stat_progress_vacuum Bharath Rupireddy <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox