On Thu, Aug 27, 2026 at 1:58 AM Heikki Linnakangas <[email protected]> wrote:
>
> On 27/08/2026 11:20, Heikki Linnakangas wrote:
> > Sorry, I missed this reply of yours earlier.
> >
> > On 27/08/2026 10:35, Masahiko Sawada wrote:
> >> On Thu, Aug 27, 2026 at 12:06 AM Chao Li <[email protected]> wrote:
> >>> bigint is a signed int64, so it cannot represent the full uint64
> >>> range, although perhaps this is only a theoretical concern. If we
> >>> want to avoid this limitation, should we use numeric instead?
> >>
> >> I'd prefer to keep bigint here. pg_get_multixact_stats() already
> >> reports num_members and members_size as int8, and both are derived
> >> from these same offsets. Also, other fields in pg_control_checkpoint()
> >> are fixed-width types, whereas numeric is pass-by-reference.
> >>
> >> I considered using xid8 instead but it has only comparison operators
> >> and no arithmetic, so we couldn't compute a delta between two
> >> checkpoints.
> >
> > Hmm, that's a good point, although 'xid' didn't have those operators or
> > arithmetic either.
>
> That was inaccurate: both 'xid' and 'xid8' do have comparison operators.
> But they don't have a "minus" or "diff" operator, so you indeed cannot
> easily do "b - a".
>
> I don't have a strong opinion, I'm happy with either bigint or xid8
> here. Bigint is probably more convenient in practice, and it's good to
> not confuse mxact offsets with transaction ids by abusing the xid8 type.
> Then again, it was 'xid' before, which had the same issues and we went
> with 'xid' anyway. Then again, now that it doesn't wrap around anymore,
> maybe 'bigint' makes more sense now.

I missed the point that we used to use 'xid' for that field. But I
agree that 'bigint' makes more sense.

> Would you like to decide and commit this, or would you prefer me to do it?

I'm going to take them and go with the 'bigint' column if you're okay.

I've added the commit messages to the patches.


Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
From 3053fd1381b36d4a28ad05e773148d21d80a25b8 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <[email protected]>
Date: Wed, 26 Aug 2026 17:44:02 -0700
Subject: [PATCH v2 1/3] pg_upgrade: Read nextMultiOffset as a 64-bit value.

Commit bd8d9c9bdfa widened MultiXactOffset to 64 bits and widened
ControlData.chkpnt_nxtmxoff accordingly, but get_control_data() still
read the "Latest checkpoint's NextMultiOffset" line with str2uint(),
which returns unsigned int.

This commit adds str2uint64(), mirroring the str2uint() helper used
for the other control file fields, and reads the offset with it.

Backpatch to v19, where MultiXactOffset was widened.

Reviewed-by: Heikki Linnakangas <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAD21AoCvzerscfU8o4ARQ793yAGHpQ72r2x5apeC_W2-k=SLCQ@mail.gmail.com
Backpatch-through: 19
---
 src/bin/pg_upgrade/controldata.c |  2 +-
 src/bin/pg_upgrade/pg_upgrade.h  |  1 +
 src/bin/pg_upgrade/util.c        | 11 +++++++++++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c
index fd772ba4f38..8c69329805b 100644
--- a/src/bin/pg_upgrade/controldata.c
+++ b/src/bin/pg_upgrade/controldata.c
@@ -352,7 +352,7 @@ get_control_data(ClusterInfo *cluster)
 				pg_fatal("%d: controldata retrieval problem", __LINE__);
 
 			p++;				/* remove ':' char */
-			cluster->controldata.chkpnt_nxtmxoff = str2uint(p);
+			cluster->controldata.chkpnt_nxtmxoff = str2uint64(p);
 			got_mxoff = true;
 		}
 		else if ((p = strstr(bufin, "First log segment after reset:")) != NULL)
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index ccd1ac0d013..92607daace5 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -496,6 +496,7 @@ void		cleanup_output_dirs(void);
 void		prep_status(const char *fmt, ...) pg_attribute_printf(1, 2);
 void		prep_status_progress(const char *fmt, ...) pg_attribute_printf(1, 2);
 unsigned int str2uint(const char *str);
+uint64		str2uint64(const char *str);
 
 
 /* version.c */
diff --git a/src/bin/pg_upgrade/util.c b/src/bin/pg_upgrade/util.c
index 08d6385b512..e7d7ab56445 100644
--- a/src/bin/pg_upgrade/util.c
+++ b/src/bin/pg_upgrade/util.c
@@ -353,3 +353,14 @@ str2uint(const char *str)
 {
 	return strtoul(str, NULL, 10);
 }
+
+/*
+ *	str2uint64()
+ *
+ *	convert string to uint64
+ */
+uint64
+str2uint64(const char *str)
+{
+	return strtou64(str, NULL, 10);
+}
-- 
2.55.0

From 7cf04d9bddb4eaa8592f2e5b050b24dd97f5f4be Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <[email protected]>
Date: Wed, 26 Aug 2026 17:44:33 -0700
Subject: [PATCH v2 2/3] Report next_multi_offset as bigint in
 pg_control_checkpoint().

Commit bd8d9c9bdfa widened MultiXactOffset to 64 bits, but
pg_control_checkpoint() still handle checkPointCopy.nextMultiOffset as
xid type and declared next_multi_offset column as xid. Since xid is 32
bits wide, an offset above 2^32 was reported truncated, while
pg_controldata printed the full value of the same field.

This commit reports the column as bigint instead. That matches
pg_get_multixact_stats(), which already reports num_members and
members_size, both derived from these same offsets, as int8.

Backpatch to v19, where MultiXactOffset was widened.

Bump catalog version.

Reviewed-by: Heikki Linnakangas <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAD21AoCvzerscfU8o4ARQ793yAGHpQ72r2x5apeC_W2-k=SLCQ@mail.gmail.com
Backpatch-through: 19
---
 doc/src/sgml/func/func-info.sgml        | 2 +-
 src/backend/utils/misc/pg_controldata.c | 2 +-
 src/include/catalog/pg_proc.dat         | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/src/sgml/func/func-info.sgml b/doc/src/sgml/func/func-info.sgml
index e3c05e8b933..2f03766b67a 100644
--- a/doc/src/sgml/func/func-info.sgml
+++ b/doc/src/sgml/func/func-info.sgml
@@ -3458,7 +3458,7 @@ acl      | {postgres=arwdDxtm/postgres,foo=r/postgres}
 
       <row>
        <entry><structfield>next_multi_offset</structfield></entry>
-       <entry><type>xid</type></entry>
+       <entry><type>bigint</type></entry>
       </row>
 
       <row>
diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c
index ab74d169c96..9014f0953e9 100644
--- a/src/backend/utils/misc/pg_controldata.c
+++ b/src/backend/utils/misc/pg_controldata.c
@@ -130,7 +130,7 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
 	values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
 	nulls[9] = false;
 
-	values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
+	values[10] = Int64GetDatum(ControlFile->checkPointCopy.nextMultiOffset);
 	nulls[10] = false;
 
 	values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f5867349d14..805a579080d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12346,7 +12346,7 @@
   descr => 'pg_controldata checkpoint state information as a function',
   proname => 'pg_control_checkpoint', provolatile => 'v',
   prorettype => 'record', proargtypes => '',
-  proallargtypes => '{pg_lsn,pg_lsn,text,int4,int4,bool,bool,text,oid,xid,xid,xid,oid,xid,xid,oid,xid,xid,int4,timestamptz}',
+  proallargtypes => '{pg_lsn,pg_lsn,text,int4,int4,bool,bool,text,oid,xid,int8,xid,oid,xid,xid,oid,xid,xid,int4,timestamptz}',
   proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
   proargnames => '{checkpoint_lsn,redo_lsn,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,logical_decoding,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,data_page_checksum_version,checkpoint_time}',
   prosrc => 'pg_control_checkpoint' },
-- 
2.55.0

Reply via email to