Subject: Define DatumGetInt8 function.

From: Kirill Reshke <[email-masked]>
Date: Mon, 29 Dec 2025 16:02:34 +0500

Hi hackers!

I am currently involved in the Cloudberry kernel rebase process[0]. We
are rebasing [0] which is based on pg-14 on pg-16 kernel. During this
process I noticed rebase conflicts introduced  by c8b2ef0. This commit
defines a number of include functions for datum conversion.

During this rebase resolution, I noticed that there is an Int8GetDatum
function, but there is no DatumGetInt8, which I want to use. All other
inline functions seem to be provided in pairs by postgres.h. So it
looks convenient to define DatumGetInt8 in postgres.h?

FPA doing just that.

[0] https://github.com/apache/cloudberry

-- 
Best regards,
Kirill Reshke

---

From: Chao Li <[email-masked]>
Date: Mon, 29 Dec 2025 19:08:25 +0800

> On Dec 29, 2025, at 19:02, Kirill Reshke <[email-masked]> wrote:
> 
> Hi hackers!
> 
> <v1-0001-Define-DatumGetInt8-function.patch>

LGTM.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

---

From: Tom Lane <[email-masked]>
Date: Mon, 29 Dec 2025 10:52:58 -0500

> looks convenient to define DatumGetInt8 in postgres.h?

I would actually turn this around and ask why we have Int8GetDatum?
We have no SQL types for which that is well-adapted.  I see no
uses of Int8GetDatum in our tree, and only three uses of
UInt8GetDatum, and all three of those look like type puns to me.
(heap_page_items is returning a smallint, and btcharskipsupport
should be using CharGetDatum.)

So from where I sit these look like an attractive nuisance that
we should remove rather than encourage use of.  If you have
some extension data type for which these make sense, that's
fine, but it doesn't mean they should be in core Postgres.

			regards, tom lane

---

From: Kirill Reshke <[email-masked]>
Date: Mon, 29 Dec 2025 21:01:10 +0500

> fine, but it doesn't mean they should be in core Postgres.

Well, OK. Removal is also fine for me, because it is at least consistent.

-- 
Best regards,
Kirill Reshke

---

From: Aleksander Alekseev <[email-masked]>
Date: Wed, 7 Jan 2026 17:03:19 +0300

Hi,

> Hmm, v1 looks good and self-contained to me. Like, anyway, making two
> commits (one for signed Int8 and one for unsigned) here is better for
> sake of atomicy?
> Anyway, I can see there are users of UInt8GetDatum, which are [0] and
> forks of Greenplum. So, I am not super-sure removing UInt8* is
> desirable.

Fair enough. Let it be a separate patch then.

--
Best regards,
Aleksander Alekseev
From 728184910b7274d64c4ea25ed3fd2bbfb875b8b7 Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <[email-masked]>
Date: Wed, 7 Jan 2026 16:36:36 +0300
Subject: [PATCH v2 2/2] Remove DatumGetUInt8 and UInt8GetDatum

These functions were rarely used and created some confusion. Replace the few
existing usages with more appropriate alternatives:

- use Int16GetDatum in heapfuncs.c
- use CharGetDatum/DatumGetChar in nbtcompare.c

Also update the char increment/decrement functions to use proper SCHAR_MIN and
SCHAR_MAX boundaries instead of 0/UCHAR_MAX.

Author: Aleksander Alekseev <[email-masked]>
Suggested-by: Tom Lane <[email-masked]>
Suggested-by: David Rowley <[email-masked]>
Discussion: https://postgr.es/m/CALdSSPhFyb9qLSHee73XtZm1CBWJNo9%2BJzFNf-zUEWCRW5yEiQ%40mail.gmail.com
---
 contrib/pageinspect/heapfuncs.c        |  2 +-
 src/backend/access/nbtree/nbtcompare.c | 16 ++++++++--------
 src/include/postgres.h                 | 19 -------------------
 3 files changed, 9 insertions(+), 28 deletions(-)

diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index 1cf0b44e731..8b35b3c337a 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -223,7 +223,7 @@ heap_page_items(PG_FUNCTION_ARGS)
 			values[7] = PointerGetDatum(&tuphdr->t_ctid);
 			values[8] = UInt32GetDatum(tuphdr->t_infomask2);
 			values[9] = UInt32GetDatum(tuphdr->t_infomask);
-			values[10] = UInt8GetDatum(tuphdr->t_hoff);
+			values[10] = Int16GetDatum(tuphdr->t_hoff);
 
 			/*
 			 * We already checked that the item is completely within the raw
diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c
index 8425805a292..2a123082d86 100644
--- a/src/backend/access/nbtree/nbtcompare.c
+++ b/src/backend/access/nbtree/nbtcompare.c
@@ -617,9 +617,9 @@ btcharcmp(PG_FUNCTION_ARGS)
 static Datum
 char_decrement(Relation rel, Datum existing, bool *underflow)
 {
-	uint8		cexisting = DatumGetUInt8(existing);
+	char		cexisting = DatumGetChar(existing);
 
-	if (cexisting == 0)
+	if (cexisting == SCHAR_MIN)
 	{
 		/* return value is undefined */
 		*underflow = true;
@@ -627,15 +627,15 @@ char_decrement(Relation rel, Datum existing, bool *underflow)
 	}
 
 	*underflow = false;
-	return CharGetDatum((uint8) cexisting - 1);
+	return CharGetDatum(cexisting - 1);
 }
 
 static Datum
 char_increment(Relation rel, Datum existing, bool *overflow)
 {
-	uint8		cexisting = DatumGetUInt8(existing);
+	char		cexisting = DatumGetChar(existing);
 
-	if (cexisting == UCHAR_MAX)
+	if (cexisting == SCHAR_MAX)
 	{
 		/* return value is undefined */
 		*overflow = true;
@@ -643,7 +643,7 @@ char_increment(Relation rel, Datum existing, bool *overflow)
 	}
 
 	*overflow = false;
-	return CharGetDatum((uint8) cexisting + 1);
+	return CharGetDatum(cexisting + 1);
 }
 
 Datum
@@ -655,8 +655,8 @@ btcharskipsupport(PG_FUNCTION_ARGS)
 	sksup->increment = char_increment;
 
 	/* btcharcmp compares chars as unsigned */
-	sksup->low_elem = UInt8GetDatum(0);
-	sksup->high_elem = UInt8GetDatum(UCHAR_MAX);
+	sksup->low_elem = CharGetDatum(SCHAR_MIN);
+	sksup->high_elem = CharGetDatum(SCHAR_MAX);
 
 	PG_RETURN_VOID();
 }
diff --git a/src/include/postgres.h b/src/include/postgres.h
index 1affc0565bc..b59b6b41e54 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -134,25 +134,6 @@ CharGetDatum(char X)
 	return (Datum) X;
 }
 
-/*
- * DatumGetUInt8
- *		Returns 8-bit unsigned integer value of a datum.
- */
-static inline uint8
-DatumGetUInt8(Datum X)
-{
-	return (uint8) X;
-}
-
-/*
- * UInt8GetDatum
- *		Returns datum representation for an 8-bit unsigned integer.
- */
-static inline Datum
-UInt8GetDatum(uint8 X)
-{
-	return (Datum) X;
-}
 
 /*
  * DatumGetInt16
-- 
2.43.0

From 8ccd133cd06d66416c9f718b10ce889a27046724 Mon Sep 17 00:00:00 2001
From: reshke <[email-masked]>
Date: Tue, 6 Jan 2026 14:03:49 +0000
Subject: [PATCH v2 1/2] Remove Int8GetDatum function.

We have no uses of Int8GetDatum in our tree and
did not have for a long time (or never).

Suggested-by: 	Tom Lane <[email-masked]>
---
 src/include/postgres.h | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/src/include/postgres.h b/src/include/postgres.h
index 7d93fbce709..1affc0565bc 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -134,16 +134,6 @@ CharGetDatum(char X)
 	return (Datum) X;
 }
 
-/*
- * Int8GetDatum
- *		Returns datum representation for an 8-bit integer.
- */
-static inline Datum
-Int8GetDatum(int8 X)
-{
-	return (Datum) X;
-}
-
 /*
  * DatumGetUInt8
  *		Returns 8-bit unsigned integer value of a datum.
-- 
2.43.0

---

From: Peter Eisentraut <[email-masked]>
Date: Wed, 11 Mar 2026 11:50:52 +0100

> Fair enough. Let it be a separate patch then.

I have committed the first patch, which removes Int8GetDatum().  (This 
is actually used by my extension pguint, but that already needed to 
provide a replacement for the non-existent DatumGetInt8(), so it's not a 
bother to provide a replacement for Int8GetDatum() for future PG versions.)

About the other patch, two points:

1) The changes in nbtcompare.c look a little messy with respect to 
signedness and unsignedness of char.  I don't know what this code 
actually does at a higher level, but the low-level details look weird. 
Like, why does char_decrement() get its input value using 
DatumGetUInt8() but makes the return value using CharGetDatum()?  And 
your patch changes the UCHAR_MAX to SCHAR_MAX but changes the variable 
from uint8 to char.  First, there is no explanation why this change from 
unsigned to unclear-sign is correct, and second, if you are using the 
char type you should then also use the matching symbol CHAR_MAX.

I'm tempted to think the correct direction here would be to use uint8 
and its associated macros and functions more rigorously, not less.

2) The change in pageinspect looks correct, but then when you look 
nearby and further around, you will find that there are also a bunch of 
(if not most) UInt16GetDatum and UInt32GetDatum that are wrong.  I think 
there is some confusion about what the "UIntNN" or "IntNN" in these 
functions refers to.  Some code appears to think that this refers to the 
input type of that function call, but it's actually more like what SQL 
data type the value will be used with.  (Some maybe it would be more 
helpful to think of it as "GetDatumForInt32" etc.)

There are a lot of opportunities to clean this up, and I suspect that 
while many of these will work either way in practice because the actual 
values don't go far enough to hit the signed/unsigned boundary, I think 
there could a number of little bugs here to be fixed.

I don't think it's worth making an isolated fix here for the one use of 
UInt8GetDatum(), especially if you believe my point 1) and we are not 
going to be removing this function anyway.

---

From: Aleksander Alekseev <[email-masked]>
Date: Fri, 13 Mar 2026 13:55:44 +0300

Hi Peter,

Thanks for your feedback.

> and its associated macros and functions more rigorously, not less.

OK, if my understanding is correct this leaves us char_increment() and
char_decrement() which currently use DatumGetUInt8 inconsistently with
CharGetDatum for the argument and return value correspondingly.

> UInt8GetDatum()

I think you meant not this particular change so I included it to the
patch. We can keep nbtcompare.c as if you believe this change is not
that important (it arguably isn't).

> The change in pageinspect looks correct, but then when you look
> (if not most) UInt16GetDatum and UInt32GetDatum that are wrong
> [...]

Agree. I did my best to fix all the inconsistencies in pageinsect.

> there could a number of little bugs here to be fixed.

I believe you were referring to places other than pageinspect. I will
investigate and create separate threads with corresponding patches
later.

-- 
Best regards,
Aleksander Alekseev
From 2b170fe6dd6f46b16802804019dc3c3aac0c2153 Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <[email-masked]>
Date: Fri, 13 Mar 2026 12:51:56 +0300
Subject: [PATCH v3] Fix several Datum conversion inconsistencies

In nbtcompare.c make char_decrement() and char_increment() use UInt8GetDatum()
consistently with DatumGetUInt8() for return values.

In pageinspect/ use Datum conversion functions matching the SQL types -
Int16GetDatum for smallint columns, Int32GetDatum for integer columns, etc.

Author: Aleksander Alekseev <[email-masked]>
Suggested-by: Peter Eisentraut <[email-masked]>
Reviewed-by: TODO FIXME
Discussion: https://postgr.es/m/CALdSSPhFyb9qLSHee73XtZm1CBWJNo9%2BJzFNf-zUEWCRW5yEiQ%40mail.gmail.com
---
 contrib/pageinspect/brinfuncs.c        |  8 ++++----
 contrib/pageinspect/btreefuncs.c       |  4 ++--
 contrib/pageinspect/ginfuncs.c         |  4 ++--
 contrib/pageinspect/gistfuncs.c        |  8 ++++----
 contrib/pageinspect/heapfuncs.c        | 20 ++++++++++----------
 contrib/pageinspect/rawpage.c          | 14 +++++++-------
 src/backend/access/nbtree/nbtcompare.c |  4 ++--
 7 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/contrib/pageinspect/brinfuncs.c b/contrib/pageinspect/brinfuncs.c
index 26cf78252ed..ec64d3e4099 100644
--- a/contrib/pageinspect/brinfuncs.c
+++ b/contrib/pageinspect/brinfuncs.c
@@ -245,7 +245,7 @@ brin_page_items(PG_FUNCTION_ARGS)
 
 		if (unusedItem)
 		{
-			values[0] = UInt16GetDatum(offset);
+			values[0] = Int32GetDatum(offset);
 			nulls[1] = true;
 			nulls[2] = true;
 			nulls[3] = true;
@@ -258,7 +258,7 @@ brin_page_items(PG_FUNCTION_ARGS)
 		{
 			int			att = attno - 1;
 
-			values[0] = UInt16GetDatum(offset);
+			values[0] = Int32GetDatum(offset);
 			switch (TupleDescAttr(rsinfo->setDesc, 1)->atttypid)
 			{
 				case INT8OID:
@@ -266,12 +266,12 @@ brin_page_items(PG_FUNCTION_ARGS)
 					break;
 				case INT4OID:
 					/* support for old extension version */
-					values[1] = UInt32GetDatum(dtup->bt_blkno);
+					values[1] = Int32GetDatum(dtup->bt_blkno);
 					break;
 				default:
 					elog(ERROR, "incorrect output types");
 			}
-			values[2] = UInt16GetDatum(attno);
+			values[2] = Int32GetDatum(attno);
 			values[3] = BoolGetDatum(dtup->bt_columns[att].bv_allnulls);
 			values[4] = BoolGetDatum(dtup->bt_columns[att].bv_hasnulls);
 			values[5] = BoolGetDatum(dtup->bt_placeholder);
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
index 0585b7cee40..3381e7cc2a7 100644
--- a/contrib/pageinspect/btreefuncs.c
+++ b/contrib/pageinspect/btreefuncs.c
@@ -507,9 +507,9 @@ bt_page_print_tuples(ua_page_items *uargs)
 
 	j = 0;
 	memset(nulls, 0, sizeof(nulls));
-	values[j++] = UInt16GetDatum(offset);
+	values[j++] = Int16GetDatum(offset);
 	values[j++] = ItemPointerGetDatum(&itup->t_tid);
-	values[j++] = Int32GetDatum((int) IndexTupleSize(itup));
+	values[j++] = Int16GetDatum(IndexTupleSize(itup));
 	values[j++] = BoolGetDatum(IndexTupleHasNulls(itup));
 	values[j++] = BoolGetDatum(IndexTupleHasVarwidths(itup));
 
diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c
index b6574083b0a..e4461db7f0a 100644
--- a/contrib/pageinspect/ginfuncs.c
+++ b/contrib/pageinspect/ginfuncs.c
@@ -73,7 +73,7 @@ gin_metapage_info(PG_FUNCTION_ARGS)
 
 	values[0] = Int64GetDatum(metadata->head);
 	values[1] = Int64GetDatum(metadata->tail);
-	values[2] = UInt32GetDatum(metadata->tailFreeSize);
+	values[2] = Int32GetDatum(metadata->tailFreeSize);
 	values[3] = Int64GetDatum(metadata->nPendingPages);
 	values[4] = Int64GetDatum(metadata->nPendingHeapTuples);
 
@@ -258,7 +258,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
 		memset(nulls, 0, sizeof(nulls));
 
 		values[0] = ItemPointerGetDatum(&cur->first);
-		values[1] = UInt16GetDatum(cur->nbytes);
+		values[1] = Int16GetDatum(cur->nbytes);
 
 		/* build an array of decoded item pointers */
 		tids = ginPostingListDecode(cur, &ndecoded);
diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c
index a205cb8a334..cb491412d00 100644
--- a/contrib/pageinspect/gistfuncs.c
+++ b/contrib/pageinspect/gistfuncs.c
@@ -176,9 +176,9 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
 
 		memset(nulls, 0, sizeof(nulls));
 
-		values[0] = UInt16GetDatum(offset);
+		values[0] = Int16GetDatum(offset);
 		values[1] = ItemPointerGetDatum(&itup->t_tid);
-		values[2] = Int32GetDatum((int) IndexTupleSize(itup));
+		values[2] = Int16GetDatum(IndexTupleSize(itup));
 
 		tuple_bytea = (bytea *) palloc(tuple_len + VARHDRSZ);
 		SET_VARSIZE(tuple_bytea, tuple_len + VARHDRSZ);
@@ -283,9 +283,9 @@ gist_page_items(PG_FUNCTION_ARGS)
 
 		memset(nulls, 0, sizeof(nulls));
 
-		values[0] = UInt16GetDatum(offset);
+		values[0] = Int16GetDatum(offset);
 		values[1] = ItemPointerGetDatum(&itup->t_tid);
-		values[2] = Int32GetDatum((int) IndexTupleSize(itup));
+		values[2] = Int16GetDatum(IndexTupleSize(itup));
 		values[3] = BoolGetDatum(ItemIdIsDead(id));
 
 		if (index_columns)
diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index 3a61954e1d9..1fba644aee8 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -189,10 +189,10 @@ heap_page_items(PG_FUNCTION_ARGS)
 		lp_flags = ItemIdGetFlags(id);
 		lp_len = ItemIdGetLength(id);
 
-		values[0] = UInt16GetDatum(inter_call_data->offset);
-		values[1] = UInt16GetDatum(lp_offset);
-		values[2] = UInt16GetDatum(lp_flags);
-		values[3] = UInt16GetDatum(lp_len);
+		values[0] = Int16GetDatum(inter_call_data->offset);
+		values[1] = Int16GetDatum(lp_offset);
+		values[2] = Int16GetDatum(lp_flags);
+		values[3] = Int16GetDatum(lp_len);
 
 		/*
 		 * We do just enough validity checking to make sure we don't reference
@@ -209,14 +209,14 @@ heap_page_items(PG_FUNCTION_ARGS)
 			/* Extract information from the tuple header */
 			tuphdr = (HeapTupleHeader) PageGetItem(page, id);
 
-			values[4] = UInt32GetDatum(HeapTupleHeaderGetRawXmin(tuphdr));
-			values[5] = UInt32GetDatum(HeapTupleHeaderGetRawXmax(tuphdr));
+			values[4] = TransactionIdGetDatum(HeapTupleHeaderGetRawXmin(tuphdr));
+			values[5] = TransactionIdGetDatum(HeapTupleHeaderGetRawXmax(tuphdr));
 			/* shared with xvac */
-			values[6] = UInt32GetDatum(HeapTupleHeaderGetRawCommandId(tuphdr));
+			values[6] = Int32GetDatum(HeapTupleHeaderGetRawCommandId(tuphdr));
 			values[7] = PointerGetDatum(&tuphdr->t_ctid);
-			values[8] = UInt32GetDatum(tuphdr->t_infomask2);
-			values[9] = UInt32GetDatum(tuphdr->t_infomask);
-			values[10] = UInt8GetDatum(tuphdr->t_hoff);
+			values[8] = Int32GetDatum(tuphdr->t_infomask2);
+			values[9] = Int32GetDatum(tuphdr->t_infomask);
+			values[10] = Int16GetDatum(tuphdr->t_hoff);
 
 			/*
 			 * We already checked that the item is completely within the raw
diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c
index 86fe245cac5..3f25a6d9ae1 100644
--- a/contrib/pageinspect/rawpage.c
+++ b/contrib/pageinspect/rawpage.c
@@ -285,8 +285,8 @@ page_header(PG_FUNCTION_ARGS)
 	}
 	else
 		values[0] = LSNGetDatum(lsn);
-	values[1] = UInt16GetDatum(pageheader->pd_checksum);
-	values[2] = UInt16GetDatum(pageheader->pd_flags);
+	values[1] = Int16GetDatum(pageheader->pd_checksum);
+	values[2] = Int16GetDatum(pageheader->pd_flags);
 
 	/* pageinspect >= 1.10 uses int4 instead of int2 for those fields */
 	switch (TupleDescAttr(tupdesc, 3)->atttypid)
@@ -295,10 +295,10 @@ page_header(PG_FUNCTION_ARGS)
 			Assert(TupleDescAttr(tupdesc, 4)->atttypid == INT2OID &&
 				   TupleDescAttr(tupdesc, 5)->atttypid == INT2OID &&
 				   TupleDescAttr(tupdesc, 6)->atttypid == INT2OID);
-			values[3] = UInt16GetDatum(pageheader->pd_lower);
-			values[4] = UInt16GetDatum(pageheader->pd_upper);
-			values[5] = UInt16GetDatum(pageheader->pd_special);
-			values[6] = UInt16GetDatum(PageGetPageSize(page));
+			values[3] = Int16GetDatum(pageheader->pd_lower);
+			values[4] = Int16GetDatum(pageheader->pd_upper);
+			values[5] = Int16GetDatum(pageheader->pd_special);
+			values[6] = Int16GetDatum(PageGetPageSize(page));
 			break;
 		case INT4OID:
 			Assert(TupleDescAttr(tupdesc, 4)->atttypid == INT4OID &&
@@ -314,7 +314,7 @@ page_header(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	values[7] = UInt16GetDatum(PageGetPageLayoutVersion(page));
+	values[7] = Int16GetDatum(PageGetPageLayoutVersion(page));
 	values[8] = TransactionIdGetDatum(pageheader->pd_prune_xid);
 
 	/* Build and return the tuple. */
diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c
index 1d343377e98..0c198259e1f 100644
--- a/src/backend/access/nbtree/nbtcompare.c
+++ b/src/backend/access/nbtree/nbtcompare.c
@@ -631,7 +631,7 @@ char_decrement(Relation rel, Datum existing, bool *underflow)
 	}
 
 	*underflow = false;
-	return CharGetDatum((uint8) cexisting - 1);
+	return UInt8GetDatum(cexisting - 1);
 }
 
 static Datum
@@ -647,7 +647,7 @@ char_increment(Relation rel, Datum existing, bool *overflow)
 	}
 
 	*overflow = false;
-	return CharGetDatum((uint8) cexisting + 1);
+	return UInt8GetDatum(cexisting + 1);
 }
 
 Datum
-- 
2.43.0

---

From: Peter Eisentraut <[email-masked]>
Date: Fri, 27 Mar 2026 13:17:15 +0100

> investigate and create separate threads with corresponding patches

I'm moving this patch to the next commitfest.  It's worth continuing to 
work on making this more correct, but AFAICT no bug has been claimed 
here, so it's not worth rushing this now.

---

From: Michael Paquier <[email-masked]>
Date: Tue, 28 Apr 2026 14:13:31 +0900

On Fri, Mar 27, 2026 at 01:17:15PM +0100, Peter Eisentraut wrote:
> I'm moving this patch to the next commitfest.  It's worth continuing to work
> on making this more correct, but AFAICT no bug has been claimed here, so
> it's not worth rushing this now.

Well, as you have pointed out at [1], this is undoing a portion of
6dcfac9696cb that has changed a set of *GetDatum() functions to match
with the C type of the variables they work on, and not the output of
the function, which is incorrect.  This means an open item standing on
top of my head for this release, that needs to be acted on.

The patch proposed at [2] handles the problem partially,
unfortunately.  I have spotted a lot more places where we use a
*GetDatum() that does not match with the data type of the SQL function
related to.  In terms of locations spotted, some notes:
- Of course, the..  cough..  places that 6dcfac9696cb has touched,
reverted now to their original form to match the SQL data type (BRIN,
pageinspect, GiST, lockfuncs.c, one in pg_buffercache).
- The IndexTupleSize() business in pageinspect is a good catch.  All
these related to smallint, used a int32 GetDatum().
- Not completely sure about the ones in nbtcompare.c, TBH.
- lockfuncs.c is much more inconsistent than I thought, even after
reverting the bits of 6dcfac9696cb.  pg_lock_status() was a mixed bag
of incorrectness (field3 for LOCKTAG_PAGE, field3 and field4 for
LOCKTAG_TUPLE, two more for PREDLOCKTAG_TUPLE).
- ginlogic.c, for triConsistentFn and consistentFmgrInfo.
nuserentries is a uint32, but the functions require Int32GetDatum() as
use int4 for the data type.
- xlogfuncs.c, pg_walfile_name_offset() should use Int32GetDatum() for
xrecoff.
- pg_proc.c, for pronargs and pronargdefaults.  Quite an old one.
- pg_logicalinspect, 4 spots for the snapshot functions.
- pg_walinspect, for various record data.
- pgstatindex, pending pages.

In short, it took me some time to put some order into all that,
finishing with the attached patch set.  0001 is the minimum for v19,
that reverts 6dcfac9696cb so as we have more *GetDatum() matching with
the types in the SQL functions.  That would take care of the open item
on top of my head.

0002 is a set of fixes that I have spotted while investigating this
set of issues in depth.  These spots are actually wrong, some of them
for a long time.  I would be slightly tempted to do something about
these in v19 rather than wait for v20, as these are somewhat latent
bugs, to have more consistency across the board.  Has anybody from the
RMT an opinion to offer?  There is not much urgency in it, still..
Added the RMT in CC for opinions.

[1]: https://www.postgresql.org/message-id/97f9375a-be61-4272-a44d-408337fe8fa6%40eisentraut.org
[2]: https://www.postgresql.org/message-id/CAJ7c6TMcGu8qmRe1gZfJ-gOzVnZq-t%3Dfwn-UuyStx1w6ZyydMw%40mail.gmail.com
--
Michael
From d777110a8e705eb69e506f56a6f33297869b7599 Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email-masked]>
Date: Tue, 28 Apr 2026 13:54:59 +0900
Subject: [PATCH 1/2] Revert "Use more consistent *GetDatum() macros for some
 unsigned numbers"

This reverts commit 6dcfac9696cb, which is wrong in trying to match the
*GetDatum() functions to match with the C types.  These should match
with the SQL functions these fields relate to.

More areas in the tree are still wrong, using Datum conversion routines
that do not match with the types of the SQL functions.  These will be
adjusted in an upcoming commit.

Reported-by: Peter Eisentraut <[email-masked]>
Discussion: https://postgr.es/m/[email-masked]
Discussion: https://postgr.es/m/CAJ7c6TMcGu8qmRe1gZfJ-gOzVnZq-t=[email-masked]
---
 src/backend/access/brin/brin_inclusion.c      | 2 +-
 src/backend/access/brin/brin_minmax.c         | 2 +-
 src/backend/access/brin/brin_minmax_multi.c   | 2 +-
 src/backend/access/gist/gistget.c             | 4 ++--
 src/backend/utils/adt/lockfuncs.c             | 4 ++--
 contrib/pageinspect/btreefuncs.c              | 2 +-
 contrib/pageinspect/ginfuncs.c                | 2 +-
 contrib/pageinspect/gistfuncs.c               | 4 ++--
 contrib/pg_buffercache/pg_buffercache_pages.c | 2 +-
 9 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 5a2058d9aad7..08890a3d0095 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -641,7 +641,7 @@ inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype,
 		tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
 								ObjectIdGetDatum(attr->atttypid),
 								ObjectIdGetDatum(subtype),
-								UInt16GetDatum(strategynum));
+								Int16GetDatum(strategynum));
 
 		if (!HeapTupleIsValid(tuple))
 			elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 732010293718..9d4e47b4dc08 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -294,7 +294,7 @@ minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype,
 		tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
 								ObjectIdGetDatum(attr->atttypid),
 								ObjectIdGetDatum(subtype),
-								UInt16GetDatum(strategynum));
+								Int16GetDatum(strategynum));
 
 		if (!HeapTupleIsValid(tuple))
 			elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index 207ae336091b..daa97164e413 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -2930,7 +2930,7 @@ minmax_multi_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype,
 		tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
 								ObjectIdGetDatum(attr->atttypid),
 								ObjectIdGetDatum(subtype),
-								UInt16GetDatum(strategynum));
+								Int16GetDatum(strategynum));
 		if (!HeapTupleIsValid(tuple))
 			elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
 				 strategynum, attr->atttypid, subtype, opfamily);
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index 4d7c100d7378..d509cc38d5db 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -231,7 +231,7 @@ gistindex_keytest(IndexScanDesc scan,
 									 key->sk_collation,
 									 PointerGetDatum(&de),
 									 key->sk_argument,
-									 UInt16GetDatum(key->sk_strategy),
+									 Int16GetDatum(key->sk_strategy),
 									 ObjectIdGetDatum(key->sk_subtype),
 									 PointerGetDatum(&recheck));
 
@@ -295,7 +295,7 @@ gistindex_keytest(IndexScanDesc scan,
 									 key->sk_collation,
 									 PointerGetDatum(&de),
 									 key->sk_argument,
-									 UInt16GetDatum(key->sk_strategy),
+									 Int16GetDatum(key->sk_strategy),
 									 ObjectIdGetDatum(key->sk_subtype),
 									 PointerGetDatum(&recheck));
 			*recheck_distances_p |= recheck;
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 4481c354fd61..dc58e9cb0a6d 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -330,7 +330,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 				values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
 				values[8] = ObjectIdGetDatum(instance->locktag.locktag_field2);
 				values[6] = ObjectIdGetDatum(instance->locktag.locktag_field3);
-				values[9] = UInt16GetDatum(instance->locktag.locktag_field4);
+				values[9] = Int16GetDatum(instance->locktag.locktag_field4);
 				nulls[2] = true;
 				nulls[3] = true;
 				nulls[4] = true;
@@ -344,7 +344,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 				values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
 				values[7] = ObjectIdGetDatum(instance->locktag.locktag_field2);
 				values[8] = ObjectIdGetDatum(instance->locktag.locktag_field3);
-				values[9] = UInt16GetDatum(instance->locktag.locktag_field4);
+				values[9] = Int16GetDatum(instance->locktag.locktag_field4);
 				nulls[2] = true;
 				nulls[3] = true;
 				nulls[4] = true;
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
index 0585b7cee402..62c905c6e7c2 100644
--- a/contrib/pageinspect/btreefuncs.c
+++ b/contrib/pageinspect/btreefuncs.c
@@ -507,7 +507,7 @@ bt_page_print_tuples(ua_page_items *uargs)
 
 	j = 0;
 	values[j++] = Int32GetDatum((int) IndexTupleSize(itup));
index b6574083b0a1..ebcc2b3db5c7 100644

diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c
index 89678d377c7b..23a4b49771d4 100644
--- a/contrib/pageinspect/gistfuncs.c
+++ b/contrib/pageinspect/gistfuncs.c
@@ -177,7 +177,7 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)

-		values[0] = UInt16GetDatum(offset);
+		values[0] = Int16GetDatum(offset);
 		values[1] = ItemPointerGetDatum(&itup->t_tid);
 		values[2] = Int32GetDatum((int) IndexTupleSize(itup));
 
@@ -284,7 +284,7 @@ gist_page_items(PG_FUNCTION_ARGS)

-		values[0] = UInt16GetDatum(offset);
+		values[0] = Int16GetDatum(offset);
 		values[1] = ItemPointerGetDatum(&itup->t_tid);
 		values[2] = Int32GetDatum((int) IndexTupleSize(itup));
 		values[3] = BoolGetDatum(ItemIdIsDead(id));
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index 1ec2cf0e6f46..bf2e6c972202 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -192,7 +192,7 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
 			nulls[5] = false;
 			values[6] = BoolGetDatum(isdirty);
 			nulls[6] = false;
-			values[7] = UInt16GetDatum(usagecount);
+			values[7] = Int16GetDatum(usagecount);
 			nulls[7] = false;
 			/* unused for v1.0 callers, but the array is always long enough */
 			values[8] = Int32GetDatum(pinning_backends);
-- 
2.53.0

From 508b5dffde0f81255bbf9133492bfb5071bfb5dc Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email-masked]>
Date: Tue, 28 Apr 2026 14:02:24 +0900
Subject: [PATCH 2/2] Fix more Datum conversion inconsistencies

This is a continuation of the work done in the previous commit, that has
undone the work of 6dcfac9696cb.  The *GetDatum() macros for output should
match with what the SQL functions use as DatumGet*() in input.

Aleksander has spotted some of the areas patched here, for pageinspect.
I have spotted the rest while digging into the state of the tree.

There is no actual behavior change after this commit, since all the
affected values are small enough that the signed bit is never used.

Author: Aleksander Alekseev <[email-masked]>
Author: Michael Paquier <[email-masked]>
Discussion: https://postgr.es/m/CAJ7c6TMcGu8qmRe1gZfJ-gOzVnZq-t=[email-masked]
---
 src/backend/access/gin/ginlogic.c             |  6 +++---
 src/backend/access/transam/xlogfuncs.c        |  2 +-
 src/backend/catalog/pg_proc.c                 |  4 ++--
 src/backend/utils/adt/lockfuncs.c             | 10 +++++-----
 contrib/pageinspect/brinfuncs.c               |  8 ++++----
 contrib/pageinspect/btreefuncs.c              |  2 +-
 contrib/pageinspect/ginfuncs.c                |  2 +-
 contrib/pageinspect/gistfuncs.c               |  4 ++--
 contrib/pageinspect/heapfuncs.c               | 18 +++++++++---------
 contrib/pageinspect/rawpage.c                 | 14 +++++++-------
 contrib/pg_logicalinspect/pg_logicalinspect.c |  8 ++++----
 contrib/pg_walinspect/pg_walinspect.c         | 14 +++++++-------
 contrib/pgstattuple/pgstatindex.c             |  2 +-
 13 files changed, 47 insertions(+), 47 deletions(-)

diff --git a/src/backend/access/gin/ginlogic.c b/src/backend/access/gin/ginlogic.c
index e851d49f74de..e59d655da623 100644
--- a/src/backend/access/gin/ginlogic.c
+++ b/src/backend/access/gin/ginlogic.c
@@ -75,7 +75,7 @@ directBoolConsistentFn(GinScanKey key)
 										  PointerGetDatum(key->entryRes),
 										  UInt16GetDatum(key->strategy),
 										  key->query,
-										  UInt32GetDatum(key->nuserentries),
+										  Int32GetDatum(key->nuserentries),
 										  PointerGetDatum(key->extra_data),
 										  PointerGetDatum(&key->recheckCurItem),
 										  PointerGetDatum(key->queryValues),
@@ -93,7 +93,7 @@ directTriConsistentFn(GinScanKey key)
 													 PointerGetDatum(key->entryRes),
 													 UInt16GetDatum(key->strategy),
 													 key->query,
-													 UInt32GetDatum(key->nuserentries),
+													 Int32GetDatum(key->nuserentries),
 													 PointerGetDatum(key->extra_data),
 													 PointerGetDatum(key->queryValues),
 													 PointerGetDatum(key->queryCategories)));
@@ -114,7 +114,7 @@ shimBoolConsistentFn(GinScanKey key)
 													   PointerGetDatum(key->entryRes),
 													   UInt16GetDatum(key->strategy),
 													   key->query,
-													   UInt32GetDatum(key->nuserentries),
+													   Int32GetDatum(key->nuserentries),
 													   PointerGetDatum(key->extra_data),
 													   PointerGetDatum(key->queryValues),
 													   PointerGetDatum(key->queryCategories)));
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 0f5979691e6b..207da27d0347 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -448,7 +448,7 @@ pg_walfile_name_offset(PG_FUNCTION_ARGS)
 	 */
 	xrecoff = XLogSegmentOffset(locationpoint, wal_segment_size);
 
-	values[1] = UInt32GetDatum(xrecoff);
+	values[1] = Int32GetDatum(xrecoff);
 	isnull[1] = false;
 
 	/*
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 5df4b3f7a91e..4c6dfb5ca908 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -342,8 +342,8 @@ ProcedureCreate(const char *procedureName,
 	values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet);
 	values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility);
 	values[Anum_pg_proc_proparallel - 1] = CharGetDatum(parallel);
-	values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount);
-	values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults));
+	values[Anum_pg_proc_pronargs - 1] = Int16GetDatum(parameterCount);
+	values[Anum_pg_proc_pronargdefaults - 1] = Int16GetDatum(list_length(parameterDefaults));
 	values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType);
 	values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes);
 	if (allParameterTypes != PointerGetDatum(NULL))
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index dc58e9cb0a6d..949b242322cb 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -271,7 +271,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 			case LOCKTAG_PAGE:
 				values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
 				values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
-				values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
+				values[3] = Int32GetDatum(instance->locktag.locktag_field3);
 				nulls[4] = true;
 				nulls[5] = true;
 				nulls[6] = true;
@@ -282,8 +282,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
 			case LOCKTAG_TUPLE:
 				values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
 				values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
-				values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
-				values[4] = UInt16GetDatum(instance->locktag.locktag_field4);
+				values[3] = Int32GetDatum(instance->locktag.locktag_field3);
+				values[4] = Int16GetDatum(instance->locktag.locktag_field4);
 				nulls[5] = true;
 				nulls[6] = true;
 				nulls[7] = true;
@@ -402,12 +402,12 @@ pg_lock_status(PG_FUNCTION_ARGS)
 		values[1] = ObjectIdGetDatum(GET_PREDICATELOCKTARGETTAG_DB(*predTag));
 		values[2] = ObjectIdGetDatum(GET_PREDICATELOCKTARGETTAG_RELATION(*predTag));
 		if (lockType == PREDLOCKTAG_TUPLE)
-			values[4] = UInt16GetDatum(GET_PREDICATELOCKTARGETTAG_OFFSET(*predTag));
+			values[4] = Int16GetDatum(GET_PREDICATELOCKTARGETTAG_OFFSET(*predTag));
 		else
 			nulls[4] = true;
 		if ((lockType == PREDLOCKTAG_TUPLE) ||
 			(lockType == PREDLOCKTAG_PAGE))
-			values[3] = UInt32GetDatum(GET_PREDICATELOCKTARGETTAG_PAGE(*predTag));
+			values[3] = Int32GetDatum(GET_PREDICATELOCKTARGETTAG_PAGE(*predTag));
 		else
 			nulls[3] = true;
 
diff --git a/contrib/pageinspect/brinfuncs.c b/contrib/pageinspect/brinfuncs.c
index 309b9522f902..c64124b5b020 100644
--- a/contrib/pageinspect/brinfuncs.c
+++ b/contrib/pageinspect/brinfuncs.c
@@ -246,7 +246,7 @@ brin_page_items(PG_FUNCTION_ARGS)
 
 		if (unusedItem)
 		{
-			values[0] = UInt16GetDatum(offset);
+			values[0] = Int32GetDatum(offset);
 			nulls[1] = true;
 			nulls[2] = true;
 			nulls[3] = true;
@@ -259,7 +259,7 @@ brin_page_items(PG_FUNCTION_ARGS)
 		{
 			int			att = attno - 1;
 
@@ -267,12 +267,12 @@ brin_page_items(PG_FUNCTION_ARGS)
index 62c905c6e7c2..3381e7cc2a74 100644
@@ -509,7 +509,7 @@ bt_page_print_tuples(ua_page_items *uargs)
 	values[j++] = Int16GetDatum(offset);
 
index ebcc2b3db5c7..e4461db7f0a2 100644

 		/* build an array of decoded item pointers */
 		tids = ginPostingListDecode(cur, &ndecoded);
diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c
index 23a4b49771d4..8f127d41ec49 100644
--- a/contrib/pageinspect/gistfuncs.c
+++ b/contrib/pageinspect/gistfuncs.c
@@ -179,7 +179,7 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
 
 		values[0] = Int16GetDatum(offset);
 		values[1] = ItemPointerGetDatum(&itup->t_tid);
-		values[2] = Int32GetDatum((int) IndexTupleSize(itup));
+		values[2] = Int16GetDatum(IndexTupleSize(itup));
 
 		tuple_bytea = (bytea *) palloc(tuple_len + VARHDRSZ);
 		SET_VARSIZE(tuple_bytea, tuple_len + VARHDRSZ);
@@ -286,7 +286,7 @@ gist_page_items(PG_FUNCTION_ARGS)
 
 		values[0] = Int16GetDatum(offset);
 
 		if (index_columns)
index 4f0f3bd53e74..7be4770dc84b 100644

 		/*
 		 * We do just enough validity checking to make sure we don't reference
@@ -209,13 +209,13 @@ heap_page_items(PG_FUNCTION_ARGS)
 			/* Extract information from the tuple header */
 			tuphdr = (HeapTupleHeader) PageGetItem(page, id);
 
 			values[10] = UInt8GetDatum(tuphdr->t_hoff);
 
 			/*
index f3996dc39fcd..d136593edb26 100644
@@ -284,8 +284,8 @@ page_header(PG_FUNCTION_ARGS)
 
@@ -294,10 +294,10 @@ page_header(PG_FUNCTION_ARGS)
@@ -313,7 +313,7 @@ page_header(PG_FUNCTION_ARGS)
 			break;
 	}

 	/* Build and return the tuple. */
diff --git a/contrib/pg_logicalinspect/pg_logicalinspect.c b/contrib/pg_logicalinspect/pg_logicalinspect.c
index 9420fa5e0c7c..389394de66b3 100644
--- a/contrib/pg_logicalinspect/pg_logicalinspect.c
+++ b/contrib/pg_logicalinspect/pg_logicalinspect.c
@@ -117,9 +117,9 @@ pg_get_logical_snapshot_meta(PG_FUNCTION_ARGS)
 	/* Validate and restore the snapshot to 'ondisk' */
 	SnapBuildRestoreSnapshot(&ondisk, lsn, CurrentMemoryContext, false);
 
-	values[i++] = UInt32GetDatum(ondisk.magic);
+	values[i++] = Int32GetDatum(ondisk.magic);
 	values[i++] = Int64GetDatum((int64) ondisk.checksum);
-	values[i++] = UInt32GetDatum(ondisk.version);
+	values[i++] = Int32GetDatum(ondisk.version);
 
 	Assert(i == PG_GET_LOGICAL_SNAPSHOT_META_COLS);
 
@@ -163,7 +163,7 @@ pg_get_logical_snapshot_info(PG_FUNCTION_ARGS)
 	values[i++] = LSNGetDatum(ondisk.builder.last_serialized_snapshot);
 	values[i++] = TransactionIdGetDatum(ondisk.builder.next_phase_at);
 
-	values[i++] = UInt32GetDatum(ondisk.builder.committed.xcnt);
+	values[i++] = Int32GetDatum(ondisk.builder.committed.xcnt);
 	if (ondisk.builder.committed.xcnt > 0)
 	{
 		Datum	   *arrayelems;
@@ -180,7 +180,7 @@ pg_get_logical_snapshot_info(PG_FUNCTION_ARGS)
 	else
 		nulls[i++] = true;
 
-	values[i++] = UInt32GetDatum(ondisk.builder.catchange.xcnt);
+	values[i++] = Int32GetDatum(ondisk.builder.catchange.xcnt);
 	if (ondisk.builder.catchange.xcnt > 0)
 	{
 		Datum	   *arrayelems;
diff --git a/contrib/pg_walinspect/pg_walinspect.c b/contrib/pg_walinspect/pg_walinspect.c
index 4cf6e41e2f5c..a172f9e2b407 100644
--- a/contrib/pg_walinspect/pg_walinspect.c
+++ b/contrib/pg_walinspect/pg_walinspect.c
@@ -230,9 +230,9 @@ GetWALRecordInfo(XLogReaderState *record, Datum *values,
 	values[i++] = TransactionIdGetDatum(XLogRecGetXid(record));
 	values[i++] = CStringGetTextDatum(desc.rm_name);
 	values[i++] = CStringGetTextDatum(record_type);
-	values[i++] = UInt32GetDatum(XLogRecGetTotalLen(record));
-	values[i++] = UInt32GetDatum(XLogRecGetDataLen(record));
-	values[i++] = UInt32GetDatum(fpi_len);
+	values[i++] = Int32GetDatum(XLogRecGetTotalLen(record));
+	values[i++] = Int32GetDatum(XLogRecGetDataLen(record));
+	values[i++] = Int32GetDatum(fpi_len);
 
 	if (rec_desc.len > 0)
 		values[i++] = CStringGetTextDatum(rec_desc.data);
@@ -357,10 +357,10 @@ GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record,
 		 * record_length, main_data_length, block_data_len, and
 		 * block_fpi_length outputs
 		 */
-		values[i++] = UInt32GetDatum(XLogRecGetTotalLen(record));
-		values[i++] = UInt32GetDatum(XLogRecGetDataLen(record));
-		values[i++] = UInt32GetDatum(block_data_len);
-		values[i++] = UInt32GetDatum(block_fpi_len);
+		values[i++] = Int32GetDatum(XLogRecGetTotalLen(record));
+		values[i++] = Int32GetDatum(XLogRecGetDataLen(record));
+		values[i++] = Int32GetDatum(block_data_len);
+		values[i++] = Int32GetDatum(block_fpi_len);
 
 		/* block_fpi_info (text array) output */
 		if (block_fpi_info)
diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c
index 3a3f2637bd95..8951ad0aac47 100644
--- a/contrib/pgstattuple/pgstatindex.c
+++ b/contrib/pgstattuple/pgstatindex.c
@@ -586,7 +586,7 @@ pgstatginindex_internal(Oid relid, FunctionCallInfo fcinfo)
 		elog(ERROR, "return type must be a row type");
 
 	values[0] = Int32GetDatum(stats.version);
-	values[1] = UInt32GetDatum(stats.pending_pages);
+	values[1] = Int32GetDatum(stats.pending_pages);
 	values[2] = Int64GetDatum(stats.pending_tuples);
 
 	/*
-- 
2.53.0

---

From: Michael Paquier <[email-masked]>
Date: Thu, 30 Apr 2026 14:28:04 +0900

> the types in the SQL functions.  That would take care of the open item

This was not completely right after a second look.  6dcfac9696cb did
not get things completely wrong, either, the brin and gist parts of
the changes were right.  I have undone the incorrect bits for now to
address the open item.

> Added the RMT in CC for opinions.

This deserves a different discussion, unrelated to DatumGetInt8().
I'll post that on a separate thread, for v20.
--
Michael