Thank you for the review!

Attached is v3 addressing your feedback:

- Changed label to "Database system identifier" for consistency
- Use PRIu64 instead of UINT64_FORMAT for gettext
- Moved option entry after "char-signedness" in getopt array
- Fixed test to use pg_controldata instead of pg_control_system()

On Wed, Jun 4, 2025 at 4:56 PM Fujii Masao <[email protected]>
wrote:

> One question about this feature: why do we need to allow
> explicitly setting the system identifier? If the goal is
> simply to ensure it's different from the original,
> wouldn't it be sufficient to let pg_resetwal generate
> a new (hopefully unique) value using existing logic,
> like what's done in GuessControlValues() or BootStrapXLOG()?


Auto-generation would cover most cases. But explicit setting is a superset
-- users who want random can generate one themselves. Explicit control
costs nothing extra and gives full flexibility for edge cases (eg,
reproducible test environments, coordinating multiple clones). pg_resetwal
users are expected to be experts, so giving more control can cover more
possible scenarios.


Nik
From eed61a7cf316ce0bb51e55fddbc3feca3fca8850 Mon Sep 17 00:00:00 2001
From: Nikolay Samokhvalov <[email protected]>
Date: Sat, 31 Jan 2026 13:12:36 -0800
Subject: [PATCH] Add --system-identifier option to pg_resetwal

Add option to manually set the database system identifier. Useful for:
- Making restored clusters distinct from originals
- Cloning clusters for testing
- Recovery attempts on corrupted clusters

v3: Address review feedback (Fujii Masao) - use "Database system
identifier" label, PRIu64 format, fix test to use pg_controldata.
---
 doc/src/sgml/ref/pg_resetwal.sgml  | 23 +++++++++++++++++++++++
 src/bin/pg_resetwal/pg_resetwal.c  | 28 ++++++++++++++++++++++++++++
 src/bin/pg_resetwal/t/001_basic.pl | 29 +++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/doc/src/sgml/ref/pg_resetwal.sgml 
b/doc/src/sgml/ref/pg_resetwal.sgml
index 41f2b1d..8dc8f6c 100644
--- a/doc/src/sgml/ref/pg_resetwal.sgml
+++ b/doc/src/sgml/ref/pg_resetwal.sgml
@@ -359,6 +359,29 @@ PostgreSQL documentation
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><option>--system-identifier=<replaceable 
class="parameter">system_identifier</replaceable></option></term>
+    <listitem>
+     <para>
+      Manually set the database system identifier.
+     </para>
+
+     <para>
+      This option should only be used in recovery scenarios where you need
+      to make a restored cluster distinct from the original, or when cloning
+      a cluster for testing purposes. The value must be a positive 64-bit
+      integer and cannot be zero.
+     </para>
+
+     <warning>
+      <para>
+       Changing the system identifier will break compatibility with existing
+       backups and standby servers. Use this option with extreme caution.
+      </para>
+     </warning>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><option>--char-signedness=<replaceable 
class="parameter">option</replaceable></option></term>
     <listitem>
diff --git a/src/bin/pg_resetwal/pg_resetwal.c 
b/src/bin/pg_resetwal/pg_resetwal.c
index 431b83a..40c4812 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -97,6 +97,9 @@ static int    wal_segsize_val;
 static bool char_signedness_given = false;
 static bool char_signedness_val;
 
+static bool sysid_given = false;
+static uint64 sysid_val;
+
 
 static TimeLineID minXlogTli = 0;
 static XLogSegNo minXlogSegNo = 0;
@@ -135,6 +138,7 @@ main(int argc, char *argv[])
                {"next-transaction-id", required_argument, NULL, 'x'},
                {"wal-segsize", required_argument, NULL, 1},
                {"char-signedness", required_argument, NULL, 2},
+               {"system-identifier", required_argument, NULL, 3},
                {NULL, 0, NULL, 0}
        };
 
@@ -352,6 +356,20 @@ main(int argc, char *argv[])
                                        break;
                                }
 
+                       case 3:
+                               errno = 0;
+                               sysid_val = strtou64(optarg, &endptr, 0);
+                               if (endptr == optarg || *endptr != '\0' || 
errno != 0)
+                               {
+                                       pg_log_error("invalid argument for 
option %s", "--system-identifier");
+                                       pg_log_error_hint("Try \"%s --help\" 
for more information.", progname);
+                                       exit(1);
+                               }
+                               if (sysid_val == 0)
+                                       pg_fatal("system identifier must not be 
0");
+                               sysid_given = true;
+                               break;
+
                        default:
                                /* getopt_long already emitted a complaint */
                                pg_log_error_hint("Try \"%s --help\" for more 
information.", progname);
@@ -510,6 +528,9 @@ main(int argc, char *argv[])
        if (char_signedness_given)
                ControlFile.default_char_signedness = char_signedness_val;
 
+       if (sysid_given)
+               ControlFile.system_identifier = sysid_val;
+
        if (minXlogSegNo > newXlogSegNo)
                newXlogSegNo = minXlogSegNo;
 
@@ -894,6 +915,12 @@ PrintNewControlValues(void)
                printf(_("Bytes per WAL segment:                %u\n"),
                           ControlFile.xlog_seg_size);
        }
+
+       if (sysid_given)
+       {
+               printf(_("Database system identifier:           %" PRIu64 "\n"),
+                          ControlFile.system_identifier);
+       }
 }
 
 
@@ -1231,6 +1258,7 @@ usage(void)
        printf(_("  -O, --multixact-offset=OFFSET    set next multitransaction 
offset\n"));
        printf(_("  -u, --oldest-transaction-id=XID  set oldest transaction 
ID\n"));
        printf(_("  -x, --next-transaction-id=XID    set next transaction 
ID\n"));
+       printf(_("      --system-identifier=SYSID    set database system 
identifier\n"));
        printf(_("      --char-signedness=OPTION     set char signedness to 
\"signed\" or \"unsigned\"\n"));
        printf(_("      --wal-segsize=SIZE           size of WAL segments, in 
megabytes\n"));
 
diff --git a/src/bin/pg_resetwal/t/001_basic.pl 
b/src/bin/pg_resetwal/t/001_basic.pl
index d686584..4fe8dbd 100644
--- a/src/bin/pg_resetwal/t/001_basic.pl
+++ b/src/bin/pg_resetwal/t/001_basic.pl
@@ -194,6 +194,35 @@ command_fails_like(
        qr/error: invalid argument for option --char-signedness/,
        'fails with incorrect --char-signedness option');
 
+# --system-identifier
+command_fails_like(
+       [ 'pg_resetwal', '--system-identifier' => 'foo', $node->data_dir ],
+       qr/error: invalid argument for option --system-identifier/,
+       'fails with incorrect --system-identifier option');
+command_fails_like(
+       [ 'pg_resetwal', '--system-identifier' => '0', $node->data_dir ],
+       qr/system identifier must not be 0/,
+       'fails with zero system identifier');
+
+# Test actual system identifier change with force flag
+$node->stop;
+my $new_sysid = '7654321098765432109';
+command_ok(
+       [ 'pg_resetwal', '-f', '--system-identifier' => $new_sysid, 
$node->data_dir ],
+       'pg_resetwal --system-identifier with force flag succeeds');
+
+# Verify the change using pg_controldata (handles uint64 correctly)
+my $controldata_output = run_command([ 'pg_controldata', $node->data_dir ]);
+my ($actual_sysid) = $controldata_output->[0] =~ /Database system 
identifier:\s+(\d+)/;
+is($actual_sysid, $new_sysid, 'system identifier was changed correctly');
+
+# Test that the server works normally after system identifier change
+$node->start;
+is($node->safe_psql("postgres", "SELECT 1;"),
+       1, 'server running and working after system identifier change');
+
+$node->stop;
+
 # run with control override options
 
 my $out = (run_command([ 'pg_resetwal', '--dry-run', $node->data_dir ]))[0];
-- 
2.49.0

Reply via email to