From 8fe607708c8291649e6eab1dbaa4159bac06b4b7 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Thu, 9 Oct 2025 16:04:07 +0800
Subject: [PATCH v8 08/20] error safe for casting integer to other types per
 pg_cast

select castsource::regtype, casttarget::regtype, castfunc,
castcontext,castmethod, pp.prosrc, pp.proname from pg_cast pc join pg_proc pp on
pp.oid = pc.castfunc and pc.castfunc > 0
and castsource::regtype = 'integer'::regtype
order by castsource::regtype;

 castsource |    casttarget    | castfunc | castcontext | castmethod |    prosrc    | proname
------------+------------------+----------+-------------+------------+--------------+---------
 integer    | bigint           |      481 | i           | f          | int48        | int8
 integer    | smallint         |      314 | a           | f          | i4toi2       | int2
 integer    | real             |      318 | i           | f          | i4tof        | float4
 integer    | double precision |      316 | i           | f          | i4tod        | float8
 integer    | numeric          |     1740 | i           | f          | int4_numeric | numeric
 integer    | money            |     3811 | a           | f          | int4_cash    | money
 integer    | boolean          |     2557 | e           | f          | int4_bool    | bool
 integer    | bytea            |     6368 | e           | f          | int4_bytea   | bytea
 integer    | "char"           |       78 | e           | f          | i4tochar     | char
 integer    | bit              |     1683 | e           | f          | bitfromint4  | bit
(10 rows)

only int4_cash, i4toi2, i4tochar need take care of error handling.  but support
for cash data type is not easy, so only i4toi2, i4tochar function refactoring.

discussion: https://postgr.es/m/CADkLM=fv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ@mail.gmail.com
---
 src/backend/utils/adt/char.c | 6 +++++-
 src/backend/utils/adt/int.c  | 5 ++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/backend/utils/adt/char.c b/src/backend/utils/adt/char.c
index 22dbfc950b1..7cf09d954e7 100644
--- a/src/backend/utils/adt/char.c
+++ b/src/backend/utils/adt/char.c
@@ -192,10 +192,14 @@ i4tochar(PG_FUNCTION_ARGS)
 	int32		arg1 = PG_GETARG_INT32(0);
 
 	if (arg1 < SCHAR_MIN || arg1 > SCHAR_MAX)
-		ereport(ERROR,
+	{
+		errsave(fcinfo->context,
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("\"char\" out of range")));
 
+		PG_RETURN_NULL();
+	}
+
 	PG_RETURN_CHAR((int8) arg1);
 }
 
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index b5781989a64..4d3ce23a4af 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -350,10 +350,13 @@ i4toi2(PG_FUNCTION_ARGS)
 	int32		arg1 = PG_GETARG_INT32(0);
 
 	if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
-		ereport(ERROR,
+	{
+		errsave(fcinfo->context,
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("smallint out of range")));
 
+		PG_RETURN_NULL();
+	}
 	PG_RETURN_INT16((int16) arg1);
 }
 
-- 
2.34.1

