From 1a0b75d018fdd4130a8ac29d80c53a7851696333 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Mon, 13 Jul 2026 16:27:01 +0800
Subject: [PATCH v32 2/3] introduce pg_proc.proerrorsafe
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

ERROR { UNSAFE | SAFE }

ERROR UNSAFE indicates that the function aborts the transaction when an error is
encountered. This is the default behavior. ERROR SAFE indicates that the
function can report an invalid result as a “soft” error instead of aborting the
transaction. Otherwise, an invalid result causes the transaction to abort, just
as it would if the function were processed normally.
------------------------------------

-- Using the below query to list all the pg_catalog function support error safe
select pp.proname, pp.prosrc
from pg_cast pc join pg_proc pp on pp.oid = pc.castfunc
join pg_type pt on pt.oid = castsource
join pg_type pt1 on pt1.oid = casttarget
and pc.castfunc > 0 and pt.typnamespace = 'pg_catalog'::regnamespace
and pt1.typnamespace = 'pg_catalog'::regnamespace and proerrorsafe is false
order by pp.proname, pp.prosrc;

Inspired-by: Henson Choi <assam258@gmail.com>
Discussion: https://postgr.es/m/CADkLM=fv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ@mail.gmail.com
Commitfest: https://commitfest.postgresql.org/patch/5941
---
 doc/src/sgml/catalogs.sgml                    |  14 +
 doc/src/sgml/ref/alter_function.sgml          |  12 +
 doc/src/sgml/ref/create_function.sgml         |  16 ++
 src/backend/catalog/pg_aggregate.c            |   1 +
 src/backend/catalog/pg_proc.c                 |   3 +
 src/backend/commands/functioncmds.c           |  52 +++-
 src/backend/commands/typecmds.c               |   4 +
 src/backend/parser/gram.y                     |   4 +
 src/backend/utils/adt/ruleutils.c             |   3 +
 src/bin/pg_dump/pg_dump.c                     |  12 +
 src/include/catalog/pg_proc.dat               | 258 +++++++++---------
 src/include/catalog/pg_proc.h                 |   4 +
 .../regress/expected/create_function_sql.out  |   8 +-
 .../regress/expected/create_procedure.out     |  12 +
 src/test/regress/expected/misc_functions.out  |  13 +
 src/test/regress/expected/opr_sanity.out      |  13 +
 src/test/regress/sql/create_function_sql.sql  |   5 +-
 src/test/regress/sql/create_procedure.sql     |   4 +
 src/test/regress/sql/misc_functions.sql       |   4 +
 src/test/regress/sql/opr_sanity.sql           |   8 +
 20 files changed, 310 insertions(+), 140 deletions(-)

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 4b474c13917..80463ad49db 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -6161,6 +6161,20 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
       </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>proerrorsafe</structfield> <type>bool</type>
+      </para>
+      <para>
+       <structfield>proerrorsafe</structfield> indicates whether a function
+       avoids aborting the transaction when an error occurs.  It is
+       <literal>true</literal> for functions that can report an invalid result
+       as a <quote>soft</quote> error instead of aborting the transaction.  It
+       is <literal>false</literal> for functions that abort the transaction when
+       an error occurs.
+      </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>pronargs</structfield> <type>int2</type>
diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml
index 8193b17f255..b6601364dac 100644
--- a/doc/src/sgml/ref/alter_function.sgml
+++ b/doc/src/sgml/ref/alter_function.sgml
@@ -39,6 +39,7 @@ ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="param
     [ NOT ] LEAKPROOF
     [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
     PARALLEL { UNSAFE | RESTRICTED | SAFE }
+    ERROR { UNSAFE | SAFE }
     COST <replaceable class="parameter">execution_cost</replaceable>
     ROWS <replaceable class="parameter">result_rows</replaceable>
     SUPPORT <replaceable class="parameter">support_function</replaceable>
@@ -223,6 +224,17 @@ ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="param
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>ERROR</literal></term>
+
+    <listitem>
+     <para>
+      Change whether the function is deemed error safe.
+      See <xref linkend="sql-createfunction"/> for details.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>LEAKPROOF</literal></term>
     <listitem>
diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml
index 91148af012d..5b211f6b16d 100644
--- a/doc/src/sgml/ref/create_function.sgml
+++ b/doc/src/sgml/ref/create_function.sgml
@@ -33,6 +33,7 @@ CREATE [ OR REPLACE ] FUNCTION
     | { CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT }
     | { [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER }
     | PARALLEL { UNSAFE | RESTRICTED | SAFE }
+    | ERROR { UNSAFE | SAFE }
     | COST <replaceable class="parameter">execution_cost</replaceable>
     | ROWS <replaceable class="parameter">result_rows</replaceable>
     | SUPPORT <replaceable class="parameter">support_function</replaceable>
@@ -463,6 +464,21 @@ CREATE [ OR REPLACE ] FUNCTION
     </listitem>
    </varlistentry>
 
+    <varlistentry>
+     <term><literal>ERROR</literal></term>
+
+     <listitem>
+      <para>
+       <literal>ERROR UNSAFE</literal> indicates that the function aborts the
+       transaction when an error is encountered. This is the default behavior.
+       <literal>ERROR SAFE</literal> indicates that the function can report an
+       invalid result as a <quote>soft</quote> error instead of aborting the
+       transaction. Otherwise, an invalid result causes the transaction to
+       abort, just as it would if the function were processed normally.
+      </para>
+     </listitem>
+    </varlistentry>
+
     <varlistentry>
      <term><literal>COST</literal> <replaceable class="parameter">execution_cost</replaceable></term>
 
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 243b952b9cc..1a1db708654 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -631,6 +631,7 @@ AggregateCreate(const char *aggName,
 							 PROVOLATILE_IMMUTABLE, /* volatility (not needed
 													 * for agg) */
 							 proparallel,
+							 false,	/* proerrorsafe */
 							 parameterTypes,	/* paramTypes */
 							 allParameterTypes, /* allParamTypes */
 							 parameterModes,	/* parameterModes */
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 4c6dfb5ca90..aaec4a7d650 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -78,6 +78,7 @@ static bool match_prosrc_to_literal(const char *prosrc, const char *literal,
  *	isStrict: strict? (proisstrict)
  *	volatility: volatility code (provolatile)
  *	parallel: parallel safety code (proparallel)
+ *	isErrorSafe: error safe? (proerrorsafe)
  *	parameterTypes: input parameter types, as an oidvector (proargtypes)
  *	allParameterTypes: all parameter types, as an OID array (proallargtypes)
  *	parameterModes: parameter modes, as a "char" array (proargmodes)
@@ -113,6 +114,7 @@ ProcedureCreate(const char *procedureName,
 				bool isStrict,
 				char volatility,
 				char parallel,
+				bool isErrorSafe,
 				oidvector *parameterTypes,
 				Datum allParameterTypes,
 				Datum parameterModes,
@@ -342,6 +344,7 @@ 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_proerrorsafe - 1] = BoolGetDatum(isErrorSafe);
 	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);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 3afd762e9dc..f2c2b9c9a05 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -526,7 +526,8 @@ compute_common_attribute(ParseState *pstate,
 						 DefElem **cost_item,
 						 DefElem **rows_item,
 						 DefElem **support_item,
-						 DefElem **parallel_item)
+						 DefElem **parallel_item,
+						 DefElem **errorsafe_item)
 {
 	if (strcmp(defel->defname, "volatility") == 0)
 	{
@@ -602,6 +603,15 @@ compute_common_attribute(ParseState *pstate,
 
 		*parallel_item = defel;
 	}
+	else if (strcmp(defel->defname, "error") == 0)
+	{
+		if (is_procedure)
+			goto procedure_error;
+		if (*errorsafe_item)
+			errorConflictingDefElem(defel, pstate);
+
+		*errorsafe_item = defel;
+	}
 	else
 		return false;
 
@@ -654,6 +664,24 @@ interpret_func_parallel(DefElem *defel)
 	}
 }
 
+static bool
+interpret_func_errorsafe(DefElem *defel)
+{
+	char	   *str = strVal(defel->arg);
+
+	if (strcmp(str, "safe") == 0)
+		return true;
+	else if (strcmp(str, "unsafe") == 0)
+		return false;
+	else
+	{
+		ereport(ERROR,
+				errcode(ERRCODE_SYNTAX_ERROR),
+				errmsg("parameter \"error\" must be SAFE or UNSAFE"));
+		return false;			/* keep compiler quiet */
+	}
+}
+
 /*
  * Update a proconfig value according to a list of VariableSetStmt items.
  *
@@ -744,7 +772,8 @@ compute_function_attributes(ParseState *pstate,
 							float4 *procost,
 							float4 *prorows,
 							Oid *prosupport,
-							char *parallel_p)
+							char *parallel_p,
+							bool *errorsafe_p)
 {
 	ListCell   *option;
 	DefElem    *as_item = NULL;
@@ -760,6 +789,7 @@ compute_function_attributes(ParseState *pstate,
 	DefElem    *rows_item = NULL;
 	DefElem    *support_item = NULL;
 	DefElem    *parallel_item = NULL;
+	DefElem    *errorsafe_item = NULL;
 
 	foreach(option, options)
 	{
@@ -805,7 +835,8 @@ compute_function_attributes(ParseState *pstate,
 										  &cost_item,
 										  &rows_item,
 										  &support_item,
-										  &parallel_item))
+										  &parallel_item,
+										  &errorsafe_item))
 		{
 			/* recognized common option */
 			continue;
@@ -853,6 +884,8 @@ compute_function_attributes(ParseState *pstate,
 		*prosupport = interpret_func_support(support_item);
 	if (parallel_item)
 		*parallel_p = interpret_func_parallel(parallel_item);
+	if (errorsafe_item)
+		*errorsafe_p = interpret_func_errorsafe(errorsafe_item);
 }
 
 
@@ -1055,7 +1088,8 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
 	bool		isWindowFunc,
 				isStrict,
 				security,
-				isLeakProof;
+				isLeakProof,
+				isErrorSafe;
 	char		volatility;
 	ArrayType  *proconfig;
 	float4		procost;
@@ -1084,6 +1118,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
 	security = false;
 	isLeakProof = false;
 	volatility = PROVOLATILE_VOLATILE;
+	isErrorSafe = false;
 	proconfig = NULL;
 	procost = -1;				/* indicates not set */
 	prorows = -1;				/* indicates not set */
@@ -1098,7 +1133,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
 								&isWindowFunc, &volatility,
 								&isStrict, &security, &isLeakProof,
 								&proconfig, &procost, &prorows,
-								&prosupport, &parallel);
+								&prosupport, &parallel, &isErrorSafe);
 
 	if (!language)
 	{
@@ -1291,6 +1326,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
 						   isStrict,
 						   volatility,
 						   parallel,
+						   isErrorSafe,
 						   parameterTypes,
 						   PointerGetDatum(allParameterTypes),
 						   PointerGetDatum(parameterModes),
@@ -1378,6 +1414,7 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
 	DefElem    *rows_item = NULL;
 	DefElem    *support_item = NULL;
 	DefElem    *parallel_item = NULL;
+	DefElem    *errorsafe_item = NULL;
 	ObjectAddress address;
 
 	rel = table_open(ProcedureRelationId, RowExclusiveLock);
@@ -1421,7 +1458,8 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
 									 &cost_item,
 									 &rows_item,
 									 &support_item,
-									 &parallel_item) == false)
+									 &parallel_item,
+									 &errorsafe_item) == false)
 			elog(ERROR, "option \"%s\" not recognized", defel->defname);
 	}
 
@@ -1487,6 +1525,8 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
 	}
 	if (parallel_item)
 		procForm->proparallel = interpret_func_parallel(parallel_item);
+	if (errorsafe_item)
+		procForm->proerrorsafe = interpret_func_errorsafe(errorsafe_item);
 	if (set_items)
 	{
 		Datum		datum;
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 871da5af40e..e03b5682d1c 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -1836,6 +1836,7 @@ makeRangeConstructors(const char *name, Oid namespace,
 								 false, /* isStrict */
 								 PROVOLATILE_IMMUTABLE, /* volatility */
 								 PROPARALLEL_SAFE,	/* parallel safety */
+								 false, /* proerrorsafe */
 								 constructorArgTypesVector, /* parameterTypes */
 								 PointerGetDatum(NULL), /* allParameterTypes */
 								 PointerGetDatum(NULL), /* parameterModes */
@@ -1907,6 +1908,7 @@ makeMultirangeConstructors(const char *name, Oid namespace,
 							 true,	/* isStrict */
 							 PROVOLATILE_IMMUTABLE, /* volatility */
 							 PROPARALLEL_SAFE,	/* parallel safety */
+							 false, /* proerrorsafe */
 							 argtypes,	/* parameterTypes */
 							 PointerGetDatum(NULL), /* allParameterTypes */
 							 PointerGetDatum(NULL), /* parameterModes */
@@ -1953,6 +1955,7 @@ makeMultirangeConstructors(const char *name, Oid namespace,
 							 true,	/* isStrict */
 							 PROVOLATILE_IMMUTABLE, /* volatility */
 							 PROPARALLEL_SAFE,	/* parallel safety */
+							 false, /* proerrorsafe */
 							 argtypes,	/* parameterTypes */
 							 PointerGetDatum(NULL), /* allParameterTypes */
 							 PointerGetDatum(NULL), /* parameterModes */
@@ -1992,6 +1995,7 @@ makeMultirangeConstructors(const char *name, Oid namespace,
 							 true,	/* isStrict */
 							 PROVOLATILE_IMMUTABLE, /* volatility */
 							 PROPARALLEL_SAFE,	/* parallel safety */
+							 false, /* proerrorsafe */
 							 argtypes,	/* parameterTypes */
 							 PointerGetDatum(allParameterTypes),	/* allParameterTypes */
 							 PointerGetDatum(parameterModes),	/* parameterModes */
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 9e05a314707..a218935f582 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -9048,6 +9048,10 @@ common_func_opt_item:
 				{
 					$$ = makeDefElem("parallel", (Node *) makeString($2), @1);
 				}
+			| ERROR_P ColId
+				{
+					$$ = makeDefElem("error", (Node *) makeString($2), @1);
+				}
 		;
 
 createfunc_opt_item:
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index b3aef797e7d..75fe8bf86ea 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3368,6 +3368,9 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
 			break;
 	}
 
+	if (proc->proerrorsafe)
+		appendStringInfoString(&buf, " ERROR SAFE");
+
 	if (proc->proisstrict)
 		appendStringInfoString(&buf, " STRICT");
 	if (proc->prosecdef)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 4948e6d80c7..30b5b838e45 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -13462,6 +13462,7 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
 	char	   *prorows;
 	char	   *prosupport;
 	char	   *proparallel;
+	char	   *proerrorsafe;
 	char	   *lanname;
 	char	  **configitems = NULL;
 	int			nconfigitems = 0;
@@ -13505,6 +13506,13 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
 		appendPQExpBufferStr(query,
 							 "proparallel,\n");
 
+		if (fout->remoteVersion >= 200000)
+			appendPQExpBufferStr(query,
+								 "proerrorsafe,\n");
+		else
+			appendPQExpBufferStr(query,
+								 "false AS proerrorsafe,\n");
+
 		if (fout->remoteVersion >= 110000)
 			appendPQExpBufferStr(query,
 								 "prokind,\n");
@@ -13569,6 +13577,7 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
 	prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
 	prosupport = PQgetvalue(res, 0, PQfnumber(res, "prosupport"));
 	proparallel = PQgetvalue(res, 0, PQfnumber(res, "proparallel"));
+	proerrorsafe = PQgetvalue(res, 0, PQfnumber(res, "proerrorsafe"));
 	lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
 
 	/*
@@ -13736,6 +13745,9 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
 					 finfo->dobj.name);
 	}
 
+	if (proerrorsafe[0] == 't')
+		appendPQExpBufferStr(q, " ERROR SAFE");
+
 	for (int i = 0; i < nconfigitems; i++)
 	{
 		/* we feel free to scribble on configitems[] here */
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3cb84359adf..088439f6ff4 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -202,7 +202,7 @@
   proargtypes => 'xid8 xid8', prosrc => 'xid8cmp' },
 { oid => '5071', descr => 'convert xid8 to xid',
   proname => 'xid', prorettype => 'xid', proargtypes => 'xid8',
-  prosrc => 'xid8toxid' },
+  prosrc => 'xid8toxid', proerrorsafe => 't' },
 { oid => '5097', descr => 'larger of two',
   proname => 'xid8_larger', prorettype => 'xid8', proargtypes => 'xid8 xid8',
   prosrc => 'xid8_larger' },
@@ -229,10 +229,10 @@
   proargtypes => 'char char', prosrc => 'charge' },
 { oid => '77', descr => 'convert char to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'char',
-  prosrc => 'chartoi4' },
+  prosrc => 'chartoi4', proerrorsafe => 't' },
 { oid => '78', descr => 'convert int4 to char',
   proname => 'char', prorettype => 'char', proargtypes => 'int4',
-  prosrc => 'i4tochar' },
+  prosrc => 'i4tochar', proerrorsafe => 't' },
 
 { oid => '79',
   proname => 'nameregexeq', prosupport => 'textregexeq_support',
@@ -410,7 +410,7 @@
   prosrc => 'on_ppath' },
 { oid => '138',
   proname => 'box_center', prorettype => 'point', proargtypes => 'box',
-  prosrc => 'box_center' },
+  prosrc => 'box_center', proerrorsafe => 't' },
 { oid => '139',
   descr => 'restriction selectivity for area-comparison operators',
   proname => 'areasel', provolatile => 's', prorettype => 'float8',
@@ -663,10 +663,10 @@
 
 { oid => '225',
   proname => 'lseg_center', prorettype => 'point', proargtypes => 'lseg',
-  prosrc => 'lseg_center' },
+  prosrc => 'lseg_center', proerrorsafe => 't' },
 { oid => '227',
   proname => 'poly_center', prorettype => 'point', proargtypes => 'polygon',
-  prosrc => 'poly_center' },
+  prosrc => 'poly_center', proerrorsafe => 't' },
 
 { oid => '228', descr => 'round to nearest integer',
   proname => 'dround', prorettype => 'float8', proargtypes => 'float8',
@@ -703,16 +703,16 @@
   prosrc => 'dlog1' },
 { oid => '235', descr => 'convert int2 to float8',
   proname => 'float8', proleakproof => 't', prorettype => 'float8',
-  proargtypes => 'int2', prosrc => 'i2tod' },
+  proargtypes => 'int2', prosrc => 'i2tod', proerrorsafe => 't' },
 { oid => '236', descr => 'convert int2 to float4',
   proname => 'float4', proleakproof => 't', prorettype => 'float4',
-  proargtypes => 'int2', prosrc => 'i2tof' },
+  proargtypes => 'int2', prosrc => 'i2tof', proerrorsafe => 't' },
 { oid => '237', descr => 'convert float8 to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'float8',
-  prosrc => 'dtoi2' },
+  prosrc => 'dtoi2', proerrorsafe => 't' },
 { oid => '238', descr => 'convert float4 to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'float4',
-  prosrc => 'ftoi2' },
+  prosrc => 'ftoi2', proerrorsafe => 't' },
 { oid => '239',
   proname => 'line_distance', prorettype => 'float8',
   proargtypes => 'line line', prosrc => 'line_distance' },
@@ -884,28 +884,28 @@
 
 { oid => '311', descr => 'convert float4 to float8',
   proname => 'float8', proleakproof => 't', prorettype => 'float8',
-  proargtypes => 'float4', prosrc => 'ftod' },
+  proargtypes => 'float4', prosrc => 'ftod', proerrorsafe => 't' },
 { oid => '312', descr => 'convert float8 to float4',
   proname => 'float4', prorettype => 'float4', proargtypes => 'float8',
-  prosrc => 'dtof' },
+  prosrc => 'dtof', proerrorsafe => 't' },
 { oid => '313', descr => 'convert int2 to int4',
   proname => 'int4', proleakproof => 't', prorettype => 'int4',
-  proargtypes => 'int2', prosrc => 'i2toi4' },
+  proargtypes => 'int2', prosrc => 'i2toi4', proerrorsafe => 't' },
 { oid => '314', descr => 'convert int4 to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'int4',
-  prosrc => 'i4toi2' },
+  prosrc => 'i4toi2', proerrorsafe => 't' },
 { oid => '316', descr => 'convert int4 to float8',
   proname => 'float8', proleakproof => 't', prorettype => 'float8',
-  proargtypes => 'int4', prosrc => 'i4tod' },
+  proargtypes => 'int4', prosrc => 'i4tod', proerrorsafe => 't' },
 { oid => '317', descr => 'convert float8 to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'float8',
-  prosrc => 'dtoi4' },
+  prosrc => 'dtoi4', proerrorsafe => 't' },
 { oid => '318', descr => 'convert int4 to float4',
   proname => 'float4', proleakproof => 't', prorettype => 'float4',
-  proargtypes => 'int4', prosrc => 'i4tof' },
+  proargtypes => 'int4', prosrc => 'i4tof', proerrorsafe => 't' },
 { oid => '319', descr => 'convert float4 to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'float4',
-  prosrc => 'ftoi4' },
+  prosrc => 'ftoi4', proerrorsafe => 't' },
 
 # Table access method handlers
 { oid => '3', descr => 'row-oriented heap table access method handler',
@@ -1175,45 +1175,45 @@
 
 { oid => '401', descr => 'convert char(n) to text',
   proname => 'text', prorettype => 'text', proargtypes => 'bpchar',
-  prosrc => 'rtrim1' },
+  prosrc => 'rtrim1', proerrorsafe => 't' },
 { oid => '406', descr => 'convert name to text',
   proname => 'text', proleakproof => 't', prorettype => 'text',
-  proargtypes => 'name', prosrc => 'name_text' },
+  proargtypes => 'name', prosrc => 'name_text', proerrorsafe => 't' },
 { oid => '407', descr => 'convert text to name',
   proname => 'name', proleakproof => 't', prorettype => 'name',
-  proargtypes => 'text', prosrc => 'text_name' },
+  proargtypes => 'text', prosrc => 'text_name', proerrorsafe => 't' },
 { oid => '408', descr => 'convert name to char(n)',
   proname => 'bpchar', prorettype => 'bpchar', proargtypes => 'name',
-  prosrc => 'name_bpchar' },
+  prosrc => 'name_bpchar', proerrorsafe => 't' },
 { oid => '409', descr => 'convert char(n) to name',
   proname => 'name', proleakproof => 't', prorettype => 'name',
-  proargtypes => 'bpchar', prosrc => 'bpchar_name' },
+  proargtypes => 'bpchar', prosrc => 'bpchar_name', proerrorsafe => 't' },
 
 { oid => '6367', descr => 'convert int2 to bytea',
   proname => 'bytea', proleakproof => 't', prorettype => 'bytea',
-  proargtypes => 'int2', prosrc => 'int2_bytea' },
+  proargtypes => 'int2', prosrc => 'int2_bytea', proerrorsafe => 't' },
 { oid => '6368', descr => 'convert int4 to bytea',
   proname => 'bytea', proleakproof => 't', prorettype => 'bytea',
-  proargtypes => 'int4', prosrc => 'int4_bytea' },
+  proargtypes => 'int4', prosrc => 'int4_bytea', proerrorsafe => 't' },
 { oid => '6369', descr => 'convert int8 to bytea',
   proname => 'bytea', proleakproof => 't', prorettype => 'bytea',
-  proargtypes => 'int8', prosrc => 'int8_bytea' },
+  proargtypes => 'int8', prosrc => 'int8_bytea', proerrorsafe => 't' },
 { oid => '6370', descr => 'convert bytea to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'bytea',
-  prosrc => 'bytea_int2' },
+  prosrc => 'bytea_int2', proerrorsafe => 't' },
 { oid => '6371', descr => 'convert bytea to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'bytea',
-  prosrc => 'bytea_int4' },
+  prosrc => 'bytea_int4', proerrorsafe => 't' },
 { oid => '6372', descr => 'convert bytea to int8',
   proname => 'int8', prorettype => 'int8', proargtypes => 'bytea',
-  prosrc => 'bytea_int8' },
+  prosrc => 'bytea_int8', proerrorsafe => 't' },
 
 { oid => '6510', descr => 'convert uuid to bytea',
   proname => 'bytea', proleakproof => 't', prorettype => 'bytea',
-  proargtypes => 'uuid', prosrc => 'uuid_bytea' },
+  proargtypes => 'uuid', prosrc => 'uuid_bytea', proerrorsafe => 't' },
 { oid => '6511', descr => 'convert bytea to uuid',
   proname => 'uuid', prorettype => 'uuid', proargtypes => 'bytea',
-  prosrc => 'bytea_uuid' },
+  prosrc => 'bytea_uuid', proerrorsafe => 't' },
 
 { oid => '449', descr => 'hash',
   proname => 'hashint2', prorettype => 'int4', proargtypes => 'int2',
@@ -1432,16 +1432,16 @@
 
 { oid => '480', descr => 'convert int8 to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'int8',
-  prosrc => 'int84' },
+  prosrc => 'int84', proerrorsafe => 't' },
 { oid => '481', descr => 'convert int4 to int8',
   proname => 'int8', proleakproof => 't', prorettype => 'int8',
-  proargtypes => 'int4', prosrc => 'int48' },
+  proargtypes => 'int4', prosrc => 'int48', proerrorsafe => 't' },
 { oid => '482', descr => 'convert int8 to float8',
   proname => 'float8', proleakproof => 't', prorettype => 'float8',
-  proargtypes => 'int8', prosrc => 'i8tod' },
+  proargtypes => 'int8', prosrc => 'i8tod', proerrorsafe => 't' },
 { oid => '483', descr => 'convert float8 to int8',
   proname => 'int8', prorettype => 'int8', proargtypes => 'float8',
-  prosrc => 'dtoi8' },
+  prosrc => 'dtoi8', proerrorsafe => 't' },
 
 # OIDS 500 - 599
 
@@ -1456,17 +1456,17 @@
 
 { oid => '652', descr => 'convert int8 to float4',
   proname => 'float4', proleakproof => 't', prorettype => 'float4',
-  proargtypes => 'int8', prosrc => 'i8tof' },
+  proargtypes => 'int8', prosrc => 'i8tof', proerrorsafe => 't' },
 { oid => '653', descr => 'convert float4 to int8',
   proname => 'int8', prorettype => 'int8', proargtypes => 'float4',
-  prosrc => 'ftoi8' },
+  prosrc => 'ftoi8', proerrorsafe => 't' },
 
 { oid => '714', descr => 'convert int8 to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'int8',
-  prosrc => 'int82' },
+  prosrc => 'int82', proerrorsafe => 't' },
 { oid => '754', descr => 'convert int2 to int8',
   proname => 'int8', proleakproof => 't', prorettype => 'int8',
-  proargtypes => 'int2', prosrc => 'int28' },
+  proargtypes => 'int2', prosrc => 'int28', proerrorsafe => 't' },
 
 { oid => '655',
   proname => 'namelt', proleakproof => 't', prorettype => 'bool',
@@ -1486,14 +1486,14 @@
 
 { oid => '668', descr => 'adjust char() to typmod length',
   proname => 'bpchar', prorettype => 'bpchar',
-  proargtypes => 'bpchar int4 bool', prosrc => 'bpchar' },
+  proargtypes => 'bpchar int4 bool', prosrc => 'bpchar', proerrorsafe => 't' },
 { oid => '3097', descr => 'planner support for varchar length coercion',
   proname => 'varchar_support', prorettype => 'internal',
   proargtypes => 'internal', prosrc => 'varchar_support' },
 { oid => '669', descr => 'adjust varchar() to typmod length',
   proname => 'varchar', prosupport => 'varchar_support',
   prorettype => 'varchar', proargtypes => 'varchar int4 bool',
-  prosrc => 'varchar' },
+  prosrc => 'varchar', proerrorsafe => 't' },
 
 { oid => '619',
   proname => 'oidvectorne', proleakproof => 't', prorettype => 'bool',
@@ -1909,7 +1909,7 @@
 
 { oid => '860', descr => 'convert char to char(n)',
   proname => 'bpchar', prorettype => 'bpchar', proargtypes => 'char',
-  prosrc => 'char_bpchar' },
+  prosrc => 'char_bpchar', proerrorsafe => 't' },
 
 { oid => '861', descr => 'name of the current database',
   proname => 'current_database', provolatile => 's', prorettype => 'name',
@@ -2003,13 +2003,13 @@
   proargtypes => 'money', prosrc => 'cash_numeric' },
 { oid => '3824', descr => 'convert numeric to money',
   proname => 'money', provolatile => 's', prorettype => 'money',
-  proargtypes => 'numeric', prosrc => 'numeric_cash' },
+  proargtypes => 'numeric', prosrc => 'numeric_cash', proerrorsafe => 't' },
 { oid => '3811', descr => 'convert int4 to money',
   proname => 'money', provolatile => 's', prorettype => 'money',
-  proargtypes => 'int4', prosrc => 'int4_cash' },
+  proargtypes => 'int4', prosrc => 'int4_cash', proerrorsafe => 't' },
 { oid => '3812', descr => 'convert int8 to money',
   proname => 'money', provolatile => 's', prorettype => 'money',
-  proargtypes => 'int8', prosrc => 'int8_cash' },
+  proargtypes => 'int8', prosrc => 'int8_cash', proerrorsafe => 't' },
 
 # OIDS 900 - 999
 
@@ -2043,10 +2043,10 @@
 
 { oid => '944', descr => 'convert text to char',
   proname => 'char', prorettype => 'char', proargtypes => 'text',
-  prosrc => 'text_char' },
+  prosrc => 'text_char', proerrorsafe => 't' },
 { oid => '946', descr => 'convert char to text',
   proname => 'text', prorettype => 'text', proargtypes => 'char',
-  prosrc => 'char_text' },
+  prosrc => 'char_text', proerrorsafe => 't' },
 
 { oid => '952', descr => 'large object open',
   proname => 'lo_open', provolatile => 'v', proparallel => 'u',
@@ -2145,7 +2145,7 @@
   prosrc => 'boxes_bound_box' },
 { oid => '981', descr => 'box diagonal',
   proname => 'diagonal', prorettype => 'lseg', proargtypes => 'box',
-  prosrc => 'box_diagonal' },
+  prosrc => 'box_diagonal', proerrorsafe => 't' },
 { oid => '982',
   proname => 'path_n_lt', prorettype => 'bool', proargtypes => 'path path',
   prosrc => 'path_n_lt' },
@@ -2498,7 +2498,7 @@
   prosrc => 'extract_interval' },
 { oid => '1174', descr => 'convert date to timestamp with time zone',
   proname => 'timestamptz', provolatile => 's', prorettype => 'timestamptz',
-  proargtypes => 'date', prosrc => 'date_timestamptz' },
+  proargtypes => 'date', prosrc => 'date_timestamptz', proerrorsafe => 't' },
 { oid => '2711',
   descr => 'promote groups of 24 hours to numbers of days and promote groups of 30 days to numbers of months',
   proname => 'justify_interval', prorettype => 'interval',
@@ -2515,7 +2515,7 @@
   prosrc => 'see system_functions.sql' },
 { oid => '1178', descr => 'convert timestamp with time zone to date',
   proname => 'date', provolatile => 's', prorettype => 'date',
-  proargtypes => 'timestamptz', prosrc => 'timestamptz_date' },
+  proargtypes => 'timestamptz', prosrc => 'timestamptz_date', proerrorsafe => 't' },
 { oid => '1181',
   descr => 'age of a transaction ID, in transactions before current transaction',
   proname => 'age', provolatile => 's', proparallel => 'r',
@@ -2576,7 +2576,7 @@
 { oid => '1200', descr => 'adjust interval precision',
   proname => 'interval', prosupport => 'interval_support',
   prorettype => 'interval', proargtypes => 'interval int4',
-  prosrc => 'interval_scale' },
+  prosrc => 'interval_scale', proerrorsafe => 't' },
 
 { oid => '1215', descr => 'get description for object id and catalog name',
   proname => 'obj_description', prolang => 'sql', procost => '100',
@@ -2714,10 +2714,10 @@
 
 { oid => '1287', descr => 'convert int8 to oid',
   proname => 'oid', prorettype => 'oid', proargtypes => 'int8',
-  prosrc => 'i8tooid' },
+  prosrc => 'i8tooid', proerrorsafe => 't' },
 { oid => '1288', descr => 'convert oid to int8',
   proname => 'int8', proleakproof => 't', prorettype => 'int8',
-  proargtypes => 'oid', prosrc => 'oidtoi8' },
+  proargtypes => 'oid', prosrc => 'oidtoi8', proerrorsafe => 't' },
 
 { oid => '1291',
   descr => 'trigger to suppress updates when new and old records match',
@@ -2869,7 +2869,7 @@
   proargtypes => 'interval interval', prosrc => 'interval_cmp' },
 { oid => '1316', descr => 'convert timestamp to time',
   proname => 'time', prorettype => 'time', proargtypes => 'timestamp',
-  prosrc => 'timestamp_time' },
+  prosrc => 'timestamp_time', proerrorsafe => 't' },
 
 { oid => '1317', descr => 'length',
   proname => 'length', prorettype => 'int4', proargtypes => 'text',
@@ -2981,7 +2981,7 @@
 
 { oid => '1370', descr => 'convert time to interval',
   proname => 'interval', proleakproof => 't', prorettype => 'interval',
-  proargtypes => 'time', prosrc => 'time_interval' },
+  proargtypes => 'time', prosrc => 'time_interval', proerrorsafe => 't' },
 { oid => '1372', descr => 'character length',
   proname => 'char_length', prorettype => 'int4', proargtypes => 'bpchar',
   prosrc => 'bpcharlen' },
@@ -3030,7 +3030,7 @@
 { oid => '1388',
   descr => 'convert timestamp with time zone to time with time zone',
   proname => 'timetz', provolatile => 's', prorettype => 'timetz',
-  proargtypes => 'timestamptz', prosrc => 'timestamptz_timetz' },
+  proargtypes => 'timestamptz', prosrc => 'timestamptz_timetz', proerrorsafe => 't' },
 
 { oid => '1373', descr => 'finite date?',
   proname => 'isfinite', prorettype => 'bool', proargtypes => 'date',
@@ -3065,10 +3065,10 @@
 
 { oid => '1400', descr => 'convert varchar to name',
   proname => 'name', proleakproof => 't', prorettype => 'name',
-  proargtypes => 'varchar', prosrc => 'text_name' },
+  proargtypes => 'varchar', prosrc => 'text_name', proerrorsafe => 't' },
 { oid => '1401', descr => 'convert name to varchar',
   proname => 'varchar', proleakproof => 't', prorettype => 'varchar',
-  proargtypes => 'name', prosrc => 'name_text' },
+  proargtypes => 'name', prosrc => 'name_text', proerrorsafe => 't' },
 
 { oid => '1402', descr => 'current schema name',
   proname => 'current_schema', provolatile => 's', proparallel => 'u',
@@ -3116,11 +3116,11 @@
   prosrc => 'line_horizontal' },
 { oid => '1416', descr => 'center of',
   proname => 'point', prorettype => 'point', proargtypes => 'circle',
-  prosrc => 'circle_center' },
+  prosrc => 'circle_center', proerrorsafe => 't' },
 
 { oid => '1419', descr => 'convert interval to time',
   proname => 'time', prorettype => 'time', proargtypes => 'interval',
-  prosrc => 'interval_time' },
+  prosrc => 'interval_time', proerrorsafe => 't' },
 
 { oid => '1421', descr => 'convert points to box',
   proname => 'box', prorettype => 'box', proargtypes => 'point point',
@@ -3203,16 +3203,16 @@
   prosrc => 'poly_npoints' },
 { oid => '1446', descr => 'convert polygon to bounding box',
   proname => 'box', prorettype => 'box', proargtypes => 'polygon',
-  prosrc => 'poly_box' },
+  prosrc => 'poly_box', proerrorsafe => 't' },
 { oid => '1447', descr => 'convert polygon to path',
   proname => 'path', prorettype => 'path', proargtypes => 'polygon',
-  prosrc => 'poly_path' },
+  prosrc => 'poly_path', proerrorsafe => 't' },
 { oid => '1448', descr => 'convert box to polygon',
   proname => 'polygon', prorettype => 'polygon', proargtypes => 'box',
-  prosrc => 'box_poly' },
+  prosrc => 'box_poly', proerrorsafe => 't' },
 { oid => '1449', descr => 'convert path to polygon',
   proname => 'polygon', prorettype => 'polygon', proargtypes => 'path',
-  prosrc => 'path_poly' },
+  prosrc => 'path_poly', proerrorsafe => 't' },
 
 { oid => '1450', descr => 'I/O',
   proname => 'circle_in', prorettype => 'circle', proargtypes => 'cstring',
@@ -3282,13 +3282,13 @@
   proargtypes => 'circle circle', prosrc => 'circle_distance' },
 { oid => '1472',
   proname => 'circle_center', prorettype => 'point', proargtypes => 'circle',
-  prosrc => 'circle_center' },
+  prosrc => 'circle_center', proerrorsafe => 't' },
 { oid => '1473', descr => 'convert point and radius to circle',
   proname => 'circle', prorettype => 'circle', proargtypes => 'point float8',
   prosrc => 'cr_circle' },
 { oid => '1474', descr => 'convert polygon to circle',
   proname => 'circle', prorettype => 'circle', proargtypes => 'polygon',
-  prosrc => 'poly_circle' },
+  prosrc => 'poly_circle', proerrorsafe => 't' },
 { oid => '1475', descr => 'convert vertex count and circle to polygon',
   proname => 'polygon', prorettype => 'polygon', proargtypes => 'int4 circle',
   prosrc => 'circle_poly' },
@@ -3303,13 +3303,13 @@
   proargtypes => 'point circle', prosrc => 'pt_contained_circle' },
 { oid => '4091', descr => 'convert point to empty box',
   proname => 'box', prorettype => 'box', proargtypes => 'point',
-  prosrc => 'point_box' },
+  prosrc => 'point_box', proerrorsafe => 't' },
 { oid => '1479', descr => 'convert box to circle',
   proname => 'circle', prorettype => 'circle', proargtypes => 'box',
-  prosrc => 'box_circle' },
+  prosrc => 'box_circle', proerrorsafe => 't' },
 { oid => '1480', descr => 'convert circle to box',
   proname => 'box', prorettype => 'box', proargtypes => 'circle',
-  prosrc => 'circle_box' },
+  prosrc => 'circle_box', proerrorsafe => 't' },
 
 { oid => '1482',
   proname => 'lseg_ne', proleakproof => 't', prorettype => 'bool',
@@ -3378,25 +3378,25 @@
 
 { oid => '1532', descr => 'center of',
   proname => 'point', prorettype => 'point', proargtypes => 'lseg',
-  prosrc => 'lseg_center' },
+  prosrc => 'lseg_center', proerrorsafe => 't' },
 { oid => '1534', descr => 'center of',
   proname => 'point', prorettype => 'point', proargtypes => 'box',
-  prosrc => 'box_center' },
+  prosrc => 'box_center', proerrorsafe => 't' },
 { oid => '1540', descr => 'center of',
   proname => 'point', prorettype => 'point', proargtypes => 'polygon',
-  prosrc => 'poly_center' },
+  prosrc => 'poly_center', proerrorsafe => 't' },
 { oid => '1541', descr => 'diagonal of',
   proname => 'lseg', prorettype => 'lseg', proargtypes => 'box',
-  prosrc => 'box_diagonal' },
+  prosrc => 'box_diagonal', proerrorsafe => 't' },
 { oid => '1542', descr => 'center of',
   proname => 'center', prorettype => 'point', proargtypes => 'box',
-  prosrc => 'box_center' },
+  prosrc => 'box_center', proerrorsafe => 't' },
 { oid => '1543', descr => 'center of',
   proname => 'center', prorettype => 'point', proargtypes => 'circle',
-  prosrc => 'circle_center' },
+  prosrc => 'circle_center', proerrorsafe => 't' },
 { oid => '1544', descr => 'convert circle to 12-vertex polygon',
   proname => 'polygon', prorettype => 'polygon', proargtypes => 'circle',
-  prosrc => 'circle_to_poly' },
+  prosrc => 'circle_to_poly', proerrorsafe => 't' },
 { oid => '1545', descr => 'number of points',
   proname => 'npoints', prorettype => 'int4', proargtypes => 'path',
   prosrc => 'path_npoints' },
@@ -3759,7 +3759,7 @@
   prosrc => 'ltrim1' },
 { oid => '882', descr => 'trim spaces from right end of string',
   proname => 'rtrim', prorettype => 'text', proargtypes => 'text',
-  prosrc => 'rtrim1' },
+  prosrc => 'rtrim1', proerrorsafe => 't' },
 { oid => '883', descr => 'extract portion of string',
   proname => 'substr', prorettype => 'text', proargtypes => 'text int4',
   prosrc => 'text_substr_no_len' },
@@ -4204,20 +4204,20 @@
   prosrc => 'bitoctetlength' },
 { oid => '1683', descr => 'convert int4 to bitstring',
   proname => 'bit', prorettype => 'bit', proargtypes => 'int4 int4',
-  prosrc => 'bitfromint4' },
+  prosrc => 'bitfromint4', proerrorsafe => 't' },
 { oid => '1684', descr => 'convert bitstring to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'bit',
-  prosrc => 'bittoint4' },
+  prosrc => 'bittoint4', proerrorsafe => 't' },
 
 { oid => '1685', descr => 'adjust bit() to typmod length',
   proname => 'bit', prorettype => 'bit', proargtypes => 'bit int4 bool',
-  prosrc => 'bit' },
+  prosrc => 'bit', proerrorsafe => 't' },
 { oid => '3158', descr => 'planner support for varbit length coercion',
   proname => 'varbit_support', prorettype => 'internal',
   proargtypes => 'internal', prosrc => 'varbit_support' },
 { oid => '1687', descr => 'adjust varbit() to typmod length',
   proname => 'varbit', prosupport => 'varbit_support', prorettype => 'varbit',
-  proargtypes => 'varbit int4 bool', prosrc => 'varbit' },
+  proargtypes => 'varbit int4 bool', prosrc => 'varbit', proerrorsafe => 't' },
 
 { oid => '1698', descr => 'position of sub-bitstring',
   proname => 'position', prorettype => 'int4', proargtypes => 'bit bit',
@@ -4332,10 +4332,10 @@
   proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_or' },
 { oid => '4123', descr => 'convert macaddr to macaddr8',
   proname => 'macaddr8', proleakproof => 't', prorettype => 'macaddr8',
-  proargtypes => 'macaddr', prosrc => 'macaddrtomacaddr8' },
+  proargtypes => 'macaddr', prosrc => 'macaddrtomacaddr8', proerrorsafe => 't' },
 { oid => '4124', descr => 'convert macaddr8 to macaddr',
   proname => 'macaddr', prorettype => 'macaddr', proargtypes => 'macaddr8',
-  prosrc => 'macaddr8tomacaddr' },
+  prosrc => 'macaddr8tomacaddr', proerrorsafe => 't' },
 { oid => '4125', descr => 'set 7th bit in macaddr8',
   proname => 'macaddr8_set7bit', prorettype => 'macaddr8',
   proargtypes => 'macaddr8', prosrc => 'macaddr8_set7bit' },
@@ -4440,13 +4440,13 @@
   prosrc => 'network_host' },
 { oid => '730', descr => 'show all parts of inet/cidr value',
   proname => 'text', prorettype => 'text', proargtypes => 'inet',
-  prosrc => 'network_show' },
+  prosrc => 'network_show', proerrorsafe => 't' },
 { oid => '1362', descr => 'hostmask of address',
   proname => 'hostmask', prorettype => 'inet', proargtypes => 'inet',
   prosrc => 'network_hostmask' },
 { oid => '1715', descr => 'convert inet to cidr',
   proname => 'cidr', prorettype => 'cidr', proargtypes => 'inet',
-  prosrc => 'inet_to_cidr' },
+  prosrc => 'inet_to_cidr', proerrorsafe => 't' },
 
 { oid => '2196', descr => 'inet address of the client',
   proname => 'inet_client_addr', proisstrict => 'f', provolatile => 's',
@@ -4599,7 +4599,7 @@
   proargtypes => 'internal', prosrc => 'numeric_support' },
 { oid => '1703', descr => 'adjust numeric to typmod precision/scale',
   proname => 'numeric', prosupport => 'numeric_support',
-  prorettype => 'numeric', proargtypes => 'numeric int4', prosrc => 'numeric' },
+  prorettype => 'numeric', proargtypes => 'numeric int4', prosrc => 'numeric', proerrorsafe => 't' },
 { oid => '1704',
   proname => 'numeric_abs', prorettype => 'numeric', proargtypes => 'numeric',
   prosrc => 'numeric_abs' },
@@ -4717,7 +4717,7 @@
   prosrc => 'numeric_trim_scale' },
 { oid => '1740', descr => 'convert int4 to numeric',
   proname => 'numeric', proleakproof => 't', prorettype => 'numeric',
-  proargtypes => 'int4', prosrc => 'int4_numeric' },
+  proargtypes => 'int4', prosrc => 'int4_numeric', proerrorsafe => 't' },
 { oid => '1741', descr => 'base 10 logarithm',
   proname => 'log', prolang => 'sql', prorettype => 'numeric',
   proargtypes => 'numeric', prosrc => 'see system_functions.sql' },
@@ -4726,19 +4726,19 @@
   proargtypes => 'numeric', prosrc => 'see system_functions.sql' },
 { oid => '1742', descr => 'convert float4 to numeric',
   proname => 'numeric', proleakproof => 't', prorettype => 'numeric',
-  proargtypes => 'float4', prosrc => 'float4_numeric' },
+  proargtypes => 'float4', prosrc => 'float4_numeric', proerrorsafe => 't' },
 { oid => '1743', descr => 'convert float8 to numeric',
   proname => 'numeric', proleakproof => 't', prorettype => 'numeric',
-  proargtypes => 'float8', prosrc => 'float8_numeric' },
+  proargtypes => 'float8', prosrc => 'float8_numeric', proerrorsafe => 't' },
 { oid => '1744', descr => 'convert numeric to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'numeric',
-  prosrc => 'numeric_int4' },
+  prosrc => 'numeric_int4', proerrorsafe => 't' },
 { oid => '1745', descr => 'convert numeric to float4',
   proname => 'float4', prorettype => 'float4', proargtypes => 'numeric',
-  prosrc => 'numeric_float4' },
+  prosrc => 'numeric_float4', proerrorsafe => 't' },
 { oid => '1746', descr => 'convert numeric to float8',
   proname => 'float8', prorettype => 'float8', proargtypes => 'numeric',
-  prosrc => 'numeric_float8' },
+  prosrc => 'numeric_float8', proerrorsafe => 't' },
 { oid => '1973', descr => 'trunc(x/y)',
   proname => 'div', prorettype => 'numeric', proargtypes => 'numeric numeric',
   prosrc => 'numeric_div_trunc' },
@@ -4783,41 +4783,41 @@
   proargtypes => 'numeric', prosrc => 'numeric_uminus' },
 { oid => '1779', descr => 'convert numeric to int8',
   proname => 'int8', prorettype => 'int8', proargtypes => 'numeric',
-  prosrc => 'numeric_int8' },
+  prosrc => 'numeric_int8', proerrorsafe => 't' },
 { oid => '1781', descr => 'convert int8 to numeric',
   proname => 'numeric', proleakproof => 't', prorettype => 'numeric',
-  proargtypes => 'int8', prosrc => 'int8_numeric' },
+  proargtypes => 'int8', prosrc => 'int8_numeric', proerrorsafe => 't' },
 { oid => '1782', descr => 'convert int2 to numeric',
   proname => 'numeric', proleakproof => 't', prorettype => 'numeric',
-  proargtypes => 'int2', prosrc => 'int2_numeric' },
+  proargtypes => 'int2', prosrc => 'int2_numeric', proerrorsafe => 't' },
 { oid => '1783', descr => 'convert numeric to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'numeric',
-  prosrc => 'numeric_int2' },
+  prosrc => 'numeric_int2', proerrorsafe => 't' },
 { oid => '6103', descr => 'convert numeric to pg_lsn',
   proname => 'pg_lsn', prorettype => 'pg_lsn', proargtypes => 'numeric',
   prosrc => 'numeric_pg_lsn' },
 
 { oid => '3556', descr => 'convert jsonb to boolean',
   proname => 'bool', prorettype => 'bool', proargtypes => 'jsonb',
-  prosrc => 'jsonb_bool' },
+  prosrc => 'jsonb_bool', proerrorsafe => 't' },
 { oid => '3449', descr => 'convert jsonb to numeric',
   proname => 'numeric', prorettype => 'numeric', proargtypes => 'jsonb',
-  prosrc => 'jsonb_numeric' },
+  prosrc => 'jsonb_numeric', proerrorsafe => 't' },
 { oid => '3450', descr => 'convert jsonb to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'jsonb',
-  prosrc => 'jsonb_int2' },
+  prosrc => 'jsonb_int2', proerrorsafe => 't' },
 { oid => '3451', descr => 'convert jsonb to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'jsonb',
-  prosrc => 'jsonb_int4' },
+  prosrc => 'jsonb_int4', proerrorsafe => 't' },
 { oid => '3452', descr => 'convert jsonb to int8',
   proname => 'int8', prorettype => 'int8', proargtypes => 'jsonb',
-  prosrc => 'jsonb_int8' },
+  prosrc => 'jsonb_int8', proerrorsafe => 't' },
 { oid => '3453', descr => 'convert jsonb to float4',
   proname => 'float4', prorettype => 'float4', proargtypes => 'jsonb',
-  prosrc => 'jsonb_float4' },
+  prosrc => 'jsonb_float4', proerrorsafe => 't' },
 { oid => '2580', descr => 'convert jsonb to float8',
   proname => 'float8', prorettype => 'float8', proargtypes => 'jsonb',
-  prosrc => 'jsonb_float8' },
+  prosrc => 'jsonb_float8', proerrorsafe => 't' },
 
 # formatting
 { oid => '1770', descr => 'format timestamp with time zone to text',
@@ -6320,7 +6320,7 @@
 { oid => '1961', descr => 'adjust timestamp precision',
   proname => 'timestamp', prosupport => 'timestamp_support',
   prorettype => 'timestamp', proargtypes => 'timestamp int4',
-  prosrc => 'timestamp_scale' },
+  prosrc => 'timestamp_scale', proerrorsafe => 't' },
 
 { oid => '1965', descr => 'larger of two',
   proname => 'oidlarger', prorettype => 'oid', proargtypes => 'oid oid',
@@ -6332,13 +6332,13 @@
 { oid => '1967', descr => 'adjust timestamptz precision',
   proname => 'timestamptz', prosupport => 'timestamp_support',
   prorettype => 'timestamptz', proargtypes => 'timestamptz int4',
-  prosrc => 'timestamptz_scale' },
+  prosrc => 'timestamptz_scale', proerrorsafe => 't' },
 { oid => '1968', descr => 'adjust time precision',
   proname => 'time', prosupport => 'time_support', prorettype => 'time',
-  proargtypes => 'time int4', prosrc => 'time_scale' },
+  proargtypes => 'time int4', prosrc => 'time_scale', proerrorsafe => 't' },
 { oid => '1969', descr => 'adjust time with time zone precision',
   proname => 'timetz', prosupport => 'time_support', prorettype => 'timetz',
-  proargtypes => 'timetz int4', prosrc => 'timetz_scale' },
+  proargtypes => 'timetz int4', prosrc => 'timetz_scale', proerrorsafe => 't' },
 
 { oid => '2003',
   proname => 'textanycat', prolang => 'sql', provolatile => 's',
@@ -6397,7 +6397,7 @@
 
 { oid => '2019', descr => 'convert timestamp with time zone to time',
   proname => 'time', provolatile => 's', prorettype => 'time',
-  proargtypes => 'timestamptz', prosrc => 'timestamptz_time' },
+  proargtypes => 'timestamptz', prosrc => 'timestamptz_time', proerrorsafe => 't' },
 { oid => '2020', descr => 'truncate timestamp to specified units',
   proname => 'date_trunc', prorettype => 'timestamp',
   proargtypes => 'text timestamp', prosrc => 'timestamp_trunc' },
@@ -6419,19 +6419,19 @@
   proargtypes => 'text timestamp', prosrc => 'extract_timestamp' },
 { oid => '2024', descr => 'convert date to timestamp',
   proname => 'timestamp', prorettype => 'timestamp', proargtypes => 'date',
-  prosrc => 'date_timestamp' },
+  prosrc => 'date_timestamp', proerrorsafe => 't' },
 { oid => '2025', descr => 'convert date and time to timestamp',
   proname => 'timestamp', prorettype => 'timestamp', proargtypes => 'date time',
   prosrc => 'datetime_timestamp' },
 { oid => '2027', descr => 'convert timestamp with time zone to timestamp',
   proname => 'timestamp', provolatile => 's', prorettype => 'timestamp',
-  proargtypes => 'timestamptz', prosrc => 'timestamptz_timestamp' },
+  proargtypes => 'timestamptz', prosrc => 'timestamptz_timestamp', proerrorsafe => 't' },
 { oid => '2028', descr => 'convert timestamp to timestamp with time zone',
   proname => 'timestamptz', provolatile => 's', prorettype => 'timestamptz',
-  proargtypes => 'timestamp', prosrc => 'timestamp_timestamptz' },
+  proargtypes => 'timestamp', prosrc => 'timestamp_timestamptz', proerrorsafe => 't' },
 { oid => '2029', descr => 'convert timestamp to date',
   proname => 'date', prorettype => 'date', proargtypes => 'timestamp',
-  prosrc => 'timestamp_date' },
+  prosrc => 'timestamp_date', proerrorsafe => 't' },
 { oid => '2031',
   proname => 'timestamp_mi', prorettype => 'interval',
   proargtypes => 'timestamp timestamp', prosrc => 'timestamp_mi' },
@@ -6517,10 +6517,10 @@
 
 { oid => '2046', descr => 'convert time with time zone to time',
   proname => 'time', prorettype => 'time', proargtypes => 'timetz',
-  prosrc => 'timetz_time' },
+  prosrc => 'timetz_time', proerrorsafe => 't' },
 { oid => '2047', descr => 'convert time to time with time zone',
   proname => 'timetz', provolatile => 's', prorettype => 'timetz',
-  proargtypes => 'time', prosrc => 'time_timetz' },
+  proargtypes => 'time', prosrc => 'time_timetz', proerrorsafe => 't' },
 { oid => '2048', descr => 'finite timestamp?',
   proname => 'isfinite', prorettype => 'bool', proargtypes => 'timestamp',
   prosrc => 'timestamp_finite' },
@@ -6579,10 +6579,10 @@
 
 { oid => '2075', descr => 'convert int8 to bitstring',
   proname => 'bit', prorettype => 'bit', proargtypes => 'int8 int4',
-  prosrc => 'bitfromint8' },
+  prosrc => 'bitfromint8', proerrorsafe => 't' },
 { oid => '2076', descr => 'convert bitstring to int8',
   proname => 'int8', prorettype => 'int8', proargtypes => 'bit',
-  prosrc => 'bittoint8' },
+  prosrc => 'bittoint8', proerrorsafe => 't' },
 
 { oid => '2077', descr => 'SHOW X as a function',
   proname => 'current_setting', provolatile => 's', prorettype => 'text',
@@ -6990,7 +6990,7 @@
 
 { oid => '2971', descr => 'convert boolean to text',
   proname => 'text', prorettype => 'text', proargtypes => 'bool',
-  prosrc => 'booltext' },
+  prosrc => 'booltext', proerrorsafe => 't' },
 
 # Aggregates (moved here from pg_aggregate for 7.3)
 
@@ -7549,7 +7549,7 @@
   proargtypes => 'text', prosrc => 'to_regtypemod' },
 { oid => '1079', descr => 'convert text to regclass',
   proname => 'regclass', provolatile => 's', prorettype => 'regclass',
-  proargtypes => 'text', prosrc => 'text_regclass' },
+  proargtypes => 'text', prosrc => 'text_regclass', proerrorsafe => 't' },
 
 { oid => '4098', descr => 'I/O',
   proname => 'regrolein', provolatile => 's', prorettype => 'regrole',
@@ -8896,10 +8896,10 @@
 
 { oid => '2557', descr => 'convert int4 to boolean',
   proname => 'bool', proleakproof => 't', prorettype => 'bool',
-  proargtypes => 'int4', prosrc => 'int4_bool' },
+  proargtypes => 'int4', prosrc => 'int4_bool', proerrorsafe => 't' },
 { oid => '2558', descr => 'convert boolean to int4',
   proname => 'int4', proleakproof => 't', prorettype => 'int4',
-  proargtypes => 'bool', prosrc => 'bool_int4' },
+  proargtypes => 'bool', prosrc => 'bool_int4', proerrorsafe => 't' },
 { oid => '2559', descr => 'current value from last used sequence',
   proname => 'lastval', provolatile => 'v', proparallel => 'u',
   prorettype => 'int8', proargtypes => '', prosrc => 'lastval' },
@@ -9280,7 +9280,7 @@
 { oid => '2896',
   descr => 'perform a non-validating parse of a character string to produce an XML value',
   proname => 'xml', provolatile => 's', prorettype => 'xml',
-  proargtypes => 'text', prosrc => 'texttoxml' },
+  proargtypes => 'text', prosrc => 'texttoxml', proerrorsafe => 't' },
 { oid => '2897', descr => 'validate an XML value',
   proname => 'xmlvalidate', prorettype => 'bool', proargtypes => 'xml text',
   prosrc => 'xmlvalidate' },
@@ -11423,7 +11423,7 @@
   proargtypes => '', prosrc => 'multirange_constructor0' },
 { oid => '4281', descr => 'int4multirange constructor',
   proname => 'int4multirange', prorettype => 'int4multirange',
-  proargtypes => 'int4range', prosrc => 'multirange_constructor1' },
+  proargtypes => 'int4range', prosrc => 'multirange_constructor1', proerrorsafe => 't' },
 { oid => '4282', descr => 'int4multirange constructor',
   proname => 'int4multirange', provariadic => 'int4range',
   prorettype => 'int4multirange', proargtypes => '_int4range',
@@ -11434,7 +11434,7 @@
   prosrc => 'multirange_constructor0' },
 { oid => '4284', descr => 'nummultirange constructor',
   proname => 'nummultirange', prorettype => 'nummultirange',
-  proargtypes => 'numrange', prosrc => 'multirange_constructor1' },
+  proargtypes => 'numrange', prosrc => 'multirange_constructor1', proerrorsafe => 't' },
 { oid => '4285', descr => 'nummultirange constructor',
   proname => 'nummultirange', provariadic => 'numrange',
   prorettype => 'nummultirange', proargtypes => '_numrange',
@@ -11445,7 +11445,7 @@
   prosrc => 'multirange_constructor0' },
 { oid => '4287', descr => 'tsmultirange constructor',
   proname => 'tsmultirange', prorettype => 'tsmultirange',
-  proargtypes => 'tsrange', prosrc => 'multirange_constructor1' },
+  proargtypes => 'tsrange', prosrc => 'multirange_constructor1', proerrorsafe => 't' },
 { oid => '4288', descr => 'tsmultirange constructor',
   proname => 'tsmultirange', provariadic => 'tsrange',
   prorettype => 'tsmultirange', proargtypes => '_tsrange',
@@ -11456,7 +11456,7 @@
   proargtypes => '', prosrc => 'multirange_constructor0' },
 { oid => '4290', descr => 'tstzmultirange constructor',
   proname => 'tstzmultirange', prorettype => 'tstzmultirange',
-  proargtypes => 'tstzrange', prosrc => 'multirange_constructor1' },
+  proargtypes => 'tstzrange', prosrc => 'multirange_constructor1', proerrorsafe => 't' },
 { oid => '4291', descr => 'tstzmultirange constructor',
   proname => 'tstzmultirange', provariadic => 'tstzrange',
   prorettype => 'tstzmultirange', proargtypes => '_tstzrange',
@@ -11467,7 +11467,7 @@
   proargtypes => '', prosrc => 'multirange_constructor0' },
 { oid => '4293', descr => 'datemultirange constructor',
   proname => 'datemultirange', prorettype => 'datemultirange',
-  proargtypes => 'daterange', prosrc => 'multirange_constructor1' },
+  proargtypes => 'daterange', prosrc => 'multirange_constructor1', proerrorsafe => 't' },
 { oid => '4294', descr => 'datemultirange constructor',
   proname => 'datemultirange', provariadic => 'daterange',
   prorettype => 'datemultirange', proargtypes => '_daterange',
@@ -11478,7 +11478,7 @@
   proargtypes => '', prosrc => 'multirange_constructor0' },
 { oid => '4296', descr => 'int8multirange constructor',
   proname => 'int8multirange', prorettype => 'int8multirange',
-  proargtypes => 'int8range', prosrc => 'multirange_constructor1' },
+  proargtypes => 'int8range', prosrc => 'multirange_constructor1', proerrorsafe => 't' },
 { oid => '4297', descr => 'int8multirange constructor',
   proname => 'int8multirange', provariadic => 'int8range',
   prorettype => 'int8multirange', proargtypes => '_int8range',
@@ -11486,7 +11486,7 @@
   prosrc => 'multirange_constructor2' },
 { oid => '4298', descr => 'anymultirange cast',
   proname => 'multirange', prorettype => 'anymultirange',
-  proargtypes => 'anyrange', prosrc => 'multirange_constructor1' },
+  proargtypes => 'anyrange', prosrc => 'multirange_constructor1', proerrorsafe => 't' },
 { oid => '4299', descr => 'aggregate transition function',
   proname => 'range_agg_transfn', proisstrict => 'f', prorettype => 'internal',
   proargtypes => 'internal anyrange', prosrc => 'range_agg_transfn' },
@@ -12666,7 +12666,7 @@
 # oid8 related functions
 { oid => '6436', descr => 'convert oid to oid8',
   proname => 'oid8', prorettype => 'oid8', proargtypes => 'oid',
-  prosrc => 'oidtooid8' },
+  prosrc => 'oidtooid8', proerrorsafe => 't' },
 { oid => '6438', descr => 'I/O',
   proname => 'oid8in', prorettype => 'oid8', proargtypes => 'cstring',
   prosrc => 'oid8in' },
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 2f9e0b695e2..789903d8b20 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -78,6 +78,9 @@ CATALOG(pg_proc,1255,ProcedureRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81,Proce
 	/* see PROPARALLEL_ categories below */
 	char		proparallel BKI_DEFAULT(s);
 
+	/* can report a soft error instead of aborting (ERROR SAFE) */
+	bool		proerrorsafe BKI_DEFAULT(f);
+
 	/* number of arguments */
 	/* Note: need not be given in pg_proc.dat; genbki.pl will compute it */
 	int16		pronargs;
@@ -209,6 +212,7 @@ extern ObjectAddress ProcedureCreate(const char *procedureName,
 									 bool isStrict,
 									 char volatility,
 									 char parallel,
+									 bool isErrorSafe,
 									 oidvector *parameterTypes,
 									 Datum allParameterTypes,
 									 Datum parameterModes,
diff --git a/src/test/regress/expected/create_function_sql.out b/src/test/regress/expected/create_function_sql.out
index 42524230d2b..f89536dbf75 100644
--- a/src/test/regress/expected/create_function_sql.out
+++ b/src/test/regress/expected/create_function_sql.out
@@ -176,7 +176,7 @@ RESET SESSION AUTHORIZATION;
 --
 CREATE FUNCTION functest_F_1(int) RETURNS bool LANGUAGE 'sql'
        AS 'SELECT $1 > 50';
-CREATE FUNCTION functest_F_2(int) RETURNS bool LANGUAGE 'sql'
+CREATE FUNCTION functest_F_2(int) RETURNS bool LANGUAGE 'sql' ERROR UNSAFE
        CALLED ON NULL INPUT AS 'SELECT $1 = 50';
 CREATE FUNCTION functest_F_3(int) RETURNS bool LANGUAGE 'sql'
        RETURNS NULL ON NULL INPUT AS 'SELECT $1 < 50';
@@ -197,6 +197,7 @@ SELECT proname, proisstrict FROM pg_proc
 
 ALTER FUNCTION functest_F_1(int) IMMUTABLE;	-- unrelated change, no effect
 ALTER FUNCTION functest_F_2(int) STRICT;
+ALTER FUNCTION functest_F_2(int) ERROR SAFE;
 ALTER FUNCTION functest_F_3(int) CALLED ON NULL INPUT;
 SELECT proname, proisstrict FROM pg_proc
        WHERE oid in ('functest_F_1'::regproc,
@@ -250,7 +251,7 @@ SELECT pg_get_functiondef('functest_F_2'::regproc);
  CREATE OR REPLACE FUNCTION temp_func_test.functest_f_2(integer)+
   RETURNS boolean                                               +
   LANGUAGE sql                                                  +
-  STRICT                                                        +
+  ERROR SAFE STRICT                                             +
  AS $function$SELECT $1 = 50$function$                          +
  
 (1 row)
@@ -259,7 +260,7 @@ SELECT pg_get_functiondef('functest_F_2'::regproc);
 -- SQL-standard body
 --
 CREATE FUNCTION functest_S_1(a text, b date) RETURNS boolean
-    LANGUAGE SQL
+    LANGUAGE SQL ERROR SAFE
     RETURN a = 'abcd' AND b > '2001-01-01';
 CREATE FUNCTION functest_S_2(a text[]) RETURNS int
     RETURN a[1]::int;
@@ -348,6 +349,7 @@ SELECT pg_get_functiondef('functest_S_1'::regproc);
  CREATE OR REPLACE FUNCTION temp_func_test.functest_s_1(a text, b date)+
   RETURNS boolean                                                      +
   LANGUAGE sql                                                         +
+  ERROR SAFE                                                           +
  RETURN ((a = 'abcd'::text) AND (b > '01-01-2001'::date))              +
  
 (1 row)
diff --git a/src/test/regress/expected/create_procedure.out b/src/test/regress/expected/create_procedure.out
index f89042cf798..15b4169b198 100644
--- a/src/test/regress/expected/create_procedure.out
+++ b/src/test/regress/expected/create_procedure.out
@@ -8,6 +8,14 @@ ERROR:  random() is not a procedure
 LINE 1: CALL random();
              ^
 HINT:  To call a function, use SELECT.
+CREATE PROCEDURE ptest1(x text) LANGUAGE SQL ERROR SAFE AS $$ $$;
+ERROR:  invalid attribute in procedure definition
+LINE 1: CREATE PROCEDURE ptest1(x text) LANGUAGE SQL ERROR SAFE AS $...
+                                                     ^
+CREATE PROCEDURE ptest1s(x text) LANGUAGE SQL ERROR SAFE BEGIN ATOMIC END;
+ERROR:  invalid attribute in procedure definition
+LINE 1: CREATE PROCEDURE ptest1s(x text) LANGUAGE SQL ERROR SAFE BEG...
+                                                      ^
 CREATE FUNCTION cp_testfunc1(a int) RETURNS int LANGUAGE SQL AS $$ SELECT a $$;
 CREATE TABLE cp_test (a int, b text);
 CREATE PROCEDURE ptest1(x text)
@@ -413,6 +421,10 @@ ALTER PROCEDURE ptest1(text) STRICT;
 ERROR:  invalid attribute in procedure definition
 LINE 1: ALTER PROCEDURE ptest1(text) STRICT;
                                      ^
+ALTER PROCEDURE ptest1(text) ERROR SAFE;
+ERROR:  invalid attribute in procedure definition
+LINE 1: ALTER PROCEDURE ptest1(text) ERROR SAFE;
+                                     ^
 ALTER FUNCTION ptest1(text) VOLATILE;  -- error: not a function
 ERROR:  ptest1(text) is not a function
 ALTER PROCEDURE cp_testfunc1(int) VOLATILE;  -- error: not a procedure
diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index c3261bff209..84d65170492 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -2,6 +2,19 @@
 \getenv libdir PG_LIBDIR
 \getenv dlsuffix PG_DLSUFFIX
 \set regresslib :libdir '/regress' :dlsuffix
+create function dummyx(int) returns void language plpgsql error unsafe as $$begin end$$;
+alter function dummyx error safe;
+select pg_get_functiondef('dummyx'::regproc);
+                pg_get_functiondef                 
+---------------------------------------------------
+ CREATE OR REPLACE FUNCTION public.dummyx(integer)+
+  RETURNS void                                    +
+  LANGUAGE plpgsql                                +
+  ERROR SAFE                                      +
+ AS $function$begin end$function$                 +
+ 
+(1 row)
+
 --
 -- num_nulls()
 --
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 6b519a65cc9..2c46135d8f0 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -1047,6 +1047,19 @@ WHERE c.castmethod = 'b' AND
  xml               | character         |        0 | a
 (10 rows)
 
+-- List build-in type cast that is not error-safe
+select pp.proname, pp.prosrc
+from pg_cast pc join pg_proc pp on pp.oid = pc.castfunc
+join pg_type pt on pt.oid = castsource
+join pg_type pt1 on pt1.oid = casttarget
+and pc.castfunc > 0 and pt.typnamespace = 'pg_catalog'::regnamespace
+and pt1.typnamespace = 'pg_catalog'::regnamespace and proerrorsafe is false
+order by pp.proname, pp.prosrc;
+ proname |    prosrc    
+---------+--------------
+ numeric | cash_numeric
+(1 row)
+
 -- **************** pg_conversion ****************
 -- Look for illegal values in pg_conversion fields.
 SELECT c.oid, c.conname
diff --git a/src/test/regress/sql/create_function_sql.sql b/src/test/regress/sql/create_function_sql.sql
index 4543273f93a..a891750a2e8 100644
--- a/src/test/regress/sql/create_function_sql.sql
+++ b/src/test/regress/sql/create_function_sql.sql
@@ -123,7 +123,7 @@ RESET SESSION AUTHORIZATION;
 --
 CREATE FUNCTION functest_F_1(int) RETURNS bool LANGUAGE 'sql'
        AS 'SELECT $1 > 50';
-CREATE FUNCTION functest_F_2(int) RETURNS bool LANGUAGE 'sql'
+CREATE FUNCTION functest_F_2(int) RETURNS bool LANGUAGE 'sql' ERROR UNSAFE
        CALLED ON NULL INPUT AS 'SELECT $1 = 50';
 CREATE FUNCTION functest_F_3(int) RETURNS bool LANGUAGE 'sql'
        RETURNS NULL ON NULL INPUT AS 'SELECT $1 < 50';
@@ -137,6 +137,7 @@ SELECT proname, proisstrict FROM pg_proc
 
 ALTER FUNCTION functest_F_1(int) IMMUTABLE;	-- unrelated change, no effect
 ALTER FUNCTION functest_F_2(int) STRICT;
+ALTER FUNCTION functest_F_2(int) ERROR SAFE;
 ALTER FUNCTION functest_F_3(int) CALLED ON NULL INPUT;
 SELECT proname, proisstrict FROM pg_proc
        WHERE oid in ('functest_F_1'::regproc,
@@ -157,7 +158,7 @@ SELECT pg_get_functiondef('functest_F_2'::regproc);
 -- SQL-standard body
 --
 CREATE FUNCTION functest_S_1(a text, b date) RETURNS boolean
-    LANGUAGE SQL
+    LANGUAGE SQL ERROR SAFE
     RETURN a = 'abcd' AND b > '2001-01-01';
 CREATE FUNCTION functest_S_2(a text[]) RETURNS int
     RETURN a[1]::int;
diff --git a/src/test/regress/sql/create_procedure.sql b/src/test/regress/sql/create_procedure.sql
index 069a3727ced..e61e053ed41 100644
--- a/src/test/regress/sql/create_procedure.sql
+++ b/src/test/regress/sql/create_procedure.sql
@@ -1,6 +1,9 @@
 CALL nonexistent();  -- error
 CALL random();  -- error
 
+CREATE PROCEDURE ptest1(x text) LANGUAGE SQL ERROR SAFE AS $$ $$;
+CREATE PROCEDURE ptest1s(x text) LANGUAGE SQL ERROR SAFE BEGIN ATOMIC END;
+
 CREATE FUNCTION cp_testfunc1(a int) RETURNS int LANGUAGE SQL AS $$ SELECT a $$;
 
 CREATE TABLE cp_test (a int, b text);
@@ -244,6 +247,7 @@ CREATE PROCEDURE ptestx(a int DEFAULT 42, b OUT int) LANGUAGE SQL
   AS $$ SELECT a $$;
 
 ALTER PROCEDURE ptest1(text) STRICT;
+ALTER PROCEDURE ptest1(text) ERROR SAFE;
 ALTER FUNCTION ptest1(text) VOLATILE;  -- error: not a function
 ALTER PROCEDURE cp_testfunc1(int) VOLATILE;  -- error: not a procedure
 ALTER PROCEDURE nonexistent() VOLATILE;
diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql
index 946ee5726cd..1f2ec5d5a93 100644
--- a/src/test/regress/sql/misc_functions.sql
+++ b/src/test/regress/sql/misc_functions.sql
@@ -4,6 +4,10 @@
 
 \set regresslib :libdir '/regress' :dlsuffix
 
+create function dummyx(int) returns void language plpgsql error unsafe as $$begin end$$;
+alter function dummyx error safe;
+select pg_get_functiondef('dummyx'::regproc);
+
 --
 -- num_nulls()
 --
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index 5670bb14193..341aa107eaf 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -517,6 +517,14 @@ WHERE c.castmethod = 'b' AND
                     k.castsource = c.casttarget AND
                     k.casttarget = c.castsource);
 
+-- List build-in type cast that is not error-safe
+select pp.proname, pp.prosrc
+from pg_cast pc join pg_proc pp on pp.oid = pc.castfunc
+join pg_type pt on pt.oid = castsource
+join pg_type pt1 on pt1.oid = casttarget
+and pc.castfunc > 0 and pt.typnamespace = 'pg_catalog'::regnamespace
+and pt1.typnamespace = 'pg_catalog'::regnamespace and proerrorsafe is false
+order by pp.proname, pp.prosrc;
 
 -- **************** pg_conversion ****************
 
-- 
2.34.1

