diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 495e449a9e..245ea5ba09 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -21,6 +21,7 @@
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "libpq/pqformat.h"
+#include "nodes/miscnodes.h"
 #include "nodes/nodeFuncs.h"
 #include "nodes/supportnodes.h"
 #include "optimizer/optimizer.h"
@@ -90,14 +91,15 @@ typedef struct ArrayIteratorData
 }			ArrayIteratorData;
 
 static bool array_isspace(char ch);
-static int	ArrayCount(const char *str, int *dim, char typdelim);
+static int	ArrayCount(const char *str, int *dim, char typdelim,
+					   void *escontext);
 static void ReadArrayStr(char *arrayStr, const char *origStr,
 						 int nitems, int ndim, int *dim,
 						 FmgrInfo *inputproc, Oid typioparam, int32 typmod,
 						 char typdelim,
 						 int typlen, bool typbyval, char typalign,
 						 Datum *values, bool *nulls,
-						 bool *hasnulls, int32 *nbytes);
+						 bool *hasnulls, int32 *nbytes, void *escontext);
 static void ReadArrayBinary(StringInfo buf, int nitems,
 							FmgrInfo *receiveproc, Oid typioparam, int32 typmod,
 							int typlen, bool typbyval, char typalign,
@@ -177,6 +179,7 @@ array_in(PG_FUNCTION_ARGS)
 	Oid			element_type = PG_GETARG_OID(1);	/* type of an array
 													 * element */
 	int32		typmod = PG_GETARG_INT32(2);	/* typmod for array elements */
+	void	   *escontext = fcinfo->context;
 	int			typlen;
 	bool		typbyval;
 	char		typalign;
@@ -188,8 +191,8 @@ array_in(PG_FUNCTION_ARGS)
 				nitems;
 	Datum	   *dataPtr;
 	bool	   *nullsPtr;
-	bool		hasnulls;
-	int32		nbytes;
+	bool		hasnulls = false;
+	int32		nbytes = 0;
 	int32		dataoffset;
 	ArrayType  *retval;
 	int			ndim,
@@ -258,7 +261,7 @@ array_in(PG_FUNCTION_ARGS)
 			break;				/* no more dimension items */
 		p++;
 		if (ndim >= MAXDIM)
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
 							ndim + 1, MAXDIM)));
@@ -266,7 +269,7 @@ array_in(PG_FUNCTION_ARGS)
 		for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++)
 			 /* skip */ ;
 		if (q == p)				/* no digits? */
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("\"[\" must introduce explicitly-specified array dimensions.")));
@@ -280,7 +283,7 @@ array_in(PG_FUNCTION_ARGS)
 			for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++)
 				 /* skip */ ;
 			if (q == p)			/* no digits? */
-				ereport(ERROR,
+				ereturn(escontext, (Datum) 0,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("malformed array literal: \"%s\"", string),
 						 errdetail("Missing array dimension value.")));
@@ -291,7 +294,7 @@ array_in(PG_FUNCTION_ARGS)
 			lBound[ndim] = 1;
 		}
 		if (*q != ']')
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Missing \"%s\" after array dimensions.",
@@ -301,7 +304,7 @@ array_in(PG_FUNCTION_ARGS)
 		ub = atoi(p);
 		p = q + 1;
 		if (ub < lBound[ndim])
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 					 errmsg("upper bound cannot be less than lower bound")));
 
@@ -313,11 +316,13 @@ array_in(PG_FUNCTION_ARGS)
 	{
 		/* No array dimensions, so intuit dimensions from brace structure */
 		if (*p != '{')
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Array value must start with \"{\" or dimension information.")));
-		ndim = ArrayCount(p, dim, typdelim);
+		ndim = ArrayCount(p, dim, typdelim, escontext);
+		if (ndim < 0)
+			PG_RETURN_NULL();
 		for (i = 0; i < ndim; i++)
 			lBound[i] = 1;
 	}
@@ -328,7 +333,7 @@ array_in(PG_FUNCTION_ARGS)
 
 		/* If array dimensions are given, expect '=' operator */
 		if (strncmp(p, ASSGN, strlen(ASSGN)) != 0)
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Missing \"%s\" after array dimensions.",
@@ -342,20 +347,22 @@ array_in(PG_FUNCTION_ARGS)
 		 * were given
 		 */
 		if (*p != '{')
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Array contents must start with \"{\".")));
-		ndim_braces = ArrayCount(p, dim_braces, typdelim);
+		ndim_braces = ArrayCount(p, dim_braces, typdelim, escontext);
+		if (ndim_braces < 0)
+			PG_RETURN_NULL();
 		if (ndim_braces != ndim)
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Specified array dimensions do not match array contents.")));
 		for (i = 0; i < ndim; ++i)
 		{
 			if (dim[i] != dim_braces[i])
-				ereport(ERROR,
+				ereturn(escontext, (Datum) 0,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("malformed array literal: \"%s\"", string),
 						 errdetail("Specified array dimensions do not match array contents.")));
@@ -372,8 +379,10 @@ array_in(PG_FUNCTION_ARGS)
 #endif
 
 	/* This checks for overflow of the array dimensions */
-	nitems = ArrayGetNItems(ndim, dim);
-	ArrayCheckBounds(ndim, dim, lBound);
+	nitems = ArrayGetNItemsSafe(ndim, dim, escontext);
+	ArrayCheckBoundsSafe(ndim, dim, lBound, escontext);
+	if (SAFE_ERROR_OCCURRED(escontext))
+		PG_RETURN_NULL();
 
 	/* Empty array? */
 	if (nitems == 0)
@@ -387,7 +396,9 @@ array_in(PG_FUNCTION_ARGS)
 				 typdelim,
 				 typlen, typbyval, typalign,
 				 dataPtr, nullsPtr,
-				 &hasnulls, &nbytes);
+				 &hasnulls, &nbytes, escontext);
+	if (SAFE_ERROR_OCCURRED(escontext))
+		PG_RETURN_NULL();
 	if (hasnulls)
 	{
 		dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
@@ -451,9 +462,11 @@ array_isspace(char ch)
  *
  * Returns number of dimensions as function result.  The axis lengths are
  * returned in dim[], which must be of size MAXDIM.
+ *
+ * If we detect an error, fill *escontext with error details and return -1.
  */
 static int
-ArrayCount(const char *str, int *dim, char typdelim)
+ArrayCount(const char *str, int *dim, char typdelim, void *escontext)
 {
 	int			nest_level = 0,
 				i;
@@ -488,11 +501,10 @@ ArrayCount(const char *str, int *dim, char typdelim)
 			{
 				case '\0':
 					/* Signal a premature end of the string */
-					ereport(ERROR,
+					ereturn(escontext, -1,
 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 							 errmsg("malformed array literal: \"%s\"", str),
 							 errdetail("Unexpected end of input.")));
-					break;
 				case '\\':
 
 					/*
@@ -504,7 +516,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
 						parse_state != ARRAY_ELEM_STARTED &&
 						parse_state != ARRAY_QUOTED_ELEM_STARTED &&
 						parse_state != ARRAY_ELEM_DELIMITED)
-						ereport(ERROR,
+						ereturn(escontext, -1,
 								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 								 errmsg("malformed array literal: \"%s\"", str),
 								 errdetail("Unexpected \"%c\" character.",
@@ -515,7 +527,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
 					if (*(ptr + 1))
 						ptr++;
 					else
-						ereport(ERROR,
+						ereturn(escontext, -1,
 								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 								 errmsg("malformed array literal: \"%s\"", str),
 								 errdetail("Unexpected end of input.")));
@@ -530,7 +542,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
 					if (parse_state != ARRAY_LEVEL_STARTED &&
 						parse_state != ARRAY_QUOTED_ELEM_STARTED &&
 						parse_state != ARRAY_ELEM_DELIMITED)
-						ereport(ERROR,
+						ereturn(escontext, -1,
 								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 								 errmsg("malformed array literal: \"%s\"", str),
 								 errdetail("Unexpected array element.")));
@@ -551,14 +563,14 @@ ArrayCount(const char *str, int *dim, char typdelim)
 						if (parse_state != ARRAY_NO_LEVEL &&
 							parse_state != ARRAY_LEVEL_STARTED &&
 							parse_state != ARRAY_LEVEL_DELIMITED)
-							ereport(ERROR,
+							ereturn(escontext, -1,
 									(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 									 errmsg("malformed array literal: \"%s\"", str),
 									 errdetail("Unexpected \"%c\" character.",
 											   '{')));
 						parse_state = ARRAY_LEVEL_STARTED;
 						if (nest_level >= MAXDIM)
-							ereport(ERROR,
+							ereturn(escontext, -1,
 									(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 									 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
 											nest_level + 1, MAXDIM)));
@@ -581,14 +593,14 @@ ArrayCount(const char *str, int *dim, char typdelim)
 							parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
 							parse_state != ARRAY_LEVEL_COMPLETED &&
 							!(nest_level == 1 && parse_state == ARRAY_LEVEL_STARTED))
-							ereport(ERROR,
+							ereturn(escontext, -1,
 									(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 									 errmsg("malformed array literal: \"%s\"", str),
 									 errdetail("Unexpected \"%c\" character.",
 											   '}')));
 						parse_state = ARRAY_LEVEL_COMPLETED;
 						if (nest_level == 0)
-							ereport(ERROR,
+							ereturn(escontext, -1,
 									(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 									 errmsg("malformed array literal: \"%s\"", str),
 									 errdetail("Unmatched \"%c\" character.", '}')));
@@ -596,7 +608,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
 
 						if (nelems_last[nest_level] != 0 &&
 							nelems[nest_level] != nelems_last[nest_level])
-							ereport(ERROR,
+							ereturn(escontext, -1,
 									(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 									 errmsg("malformed array literal: \"%s\"", str),
 									 errdetail("Multidimensional arrays must have "
@@ -630,7 +642,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
 								parse_state != ARRAY_ELEM_COMPLETED &&
 								parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
 								parse_state != ARRAY_LEVEL_COMPLETED)
-								ereport(ERROR,
+								ereturn(escontext, -1,
 										(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 										 errmsg("malformed array literal: \"%s\"", str),
 										 errdetail("Unexpected \"%c\" character.",
@@ -653,7 +665,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
 							if (parse_state != ARRAY_LEVEL_STARTED &&
 								parse_state != ARRAY_ELEM_STARTED &&
 								parse_state != ARRAY_ELEM_DELIMITED)
-								ereport(ERROR,
+								ereturn(escontext, -1,
 										(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 										 errmsg("malformed array literal: \"%s\"", str),
 										 errdetail("Unexpected array element.")));
@@ -673,7 +685,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
 	while (*ptr)
 	{
 		if (!array_isspace(*ptr++))
-			ereport(ERROR,
+			ereturn(escontext, -1,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", str),
 					 errdetail("Junk after closing right brace.")));
@@ -713,9 +725,14 @@ ArrayCount(const char *str, int *dim, char typdelim)
  *	*hasnulls: set true iff there are any null elements.
  *	*nbytes: set to total size of data area needed (including alignment
  *		padding but not including array header overhead).
+ *	*escontext: if this points to an ErrorSaveContext, details of
+ *		any error are reported there.
  *
  * Note that values[] and nulls[] are allocated by the caller, and must have
  * nitems elements.
+ *
+ * If escontext isn't NULL, caller must check for "safe" errors by
+ * examining the escontext.
  */
 static void
 ReadArrayStr(char *arrayStr,
@@ -733,7 +750,8 @@ ReadArrayStr(char *arrayStr,
 			 Datum *values,
 			 bool *nulls,
 			 bool *hasnulls,
-			 int32 *nbytes)
+			 int32 *nbytes,
+			 void *escontext)
 {
 	int			i,
 				nest_level = 0;
@@ -784,7 +802,7 @@ ReadArrayStr(char *arrayStr,
 			{
 				case '\0':
 					/* Signal a premature end of the string */
-					ereport(ERROR,
+					ereturn(escontext,,
 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 							 errmsg("malformed array literal: \"%s\"",
 									origStr)));
@@ -793,7 +811,7 @@ ReadArrayStr(char *arrayStr,
 					/* Skip backslash, copy next character as-is. */
 					srcptr++;
 					if (*srcptr == '\0')
-						ereport(ERROR,
+						ereturn(escontext,,
 								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 								 errmsg("malformed array literal: \"%s\"",
 										origStr)));
@@ -823,7 +841,7 @@ ReadArrayStr(char *arrayStr,
 					if (!in_quotes)
 					{
 						if (nest_level >= ndim)
-							ereport(ERROR,
+							ereturn(escontext,,
 									(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 									 errmsg("malformed array literal: \"%s\"",
 											origStr)));
@@ -838,7 +856,7 @@ ReadArrayStr(char *arrayStr,
 					if (!in_quotes)
 					{
 						if (nest_level == 0)
-							ereport(ERROR,
+							ereturn(escontext,,
 									(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 									 errmsg("malformed array literal: \"%s\"",
 											origStr)));
@@ -891,7 +909,7 @@ ReadArrayStr(char *arrayStr,
 		*dstendptr = '\0';
 
 		if (i < 0 || i >= nitems)
-			ereport(ERROR,
+			ereturn(escontext,,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"",
 							origStr)));
@@ -900,16 +918,20 @@ ReadArrayStr(char *arrayStr,
 			pg_strcasecmp(itemstart, "NULL") == 0)
 		{
 			/* it's a NULL item */
-			values[i] = InputFunctionCall(inputproc, NULL,
-										  typioparam, typmod);
+			values[i] = InputFunctionCallSafe(inputproc, NULL,
+											  typioparam, typmod,
+											  escontext);
 			nulls[i] = true;
 		}
 		else
 		{
-			values[i] = InputFunctionCall(inputproc, itemstart,
-										  typioparam, typmod);
+			values[i] = InputFunctionCallSafe(inputproc, itemstart,
+											  typioparam, typmod,
+											  escontext);
 			nulls[i] = false;
 		}
+		if (SAFE_ERROR_OCCURRED(escontext))
+			return;
 	}
 
 	/*
@@ -930,7 +952,7 @@ ReadArrayStr(char *arrayStr,
 			totbytes = att_align_nominal(totbytes, typalign);
 			/* check for overflow of total request */
 			if (!AllocSizeIsValid(totbytes))
-				ereport(ERROR,
+				ereturn(escontext,,
 						(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 						 errmsg("array size exceeds the maximum allowed (%d)",
 								(int) MaxAllocSize)));
diff --git a/src/backend/utils/adt/arrayutils.c b/src/backend/utils/adt/arrayutils.c
index 051169a149..2868f4ef10 100644
--- a/src/backend/utils/adt/arrayutils.c
+++ b/src/backend/utils/adt/arrayutils.c
@@ -74,6 +74,16 @@ ArrayGetOffset0(int n, const int *tup, const int *scale)
  */
 int
 ArrayGetNItems(int ndim, const int *dims)
+{
+	return ArrayGetNItemsSafe(ndim, dims, NULL);
+}
+
+/*
+ * This entry point can return the error into an ErrorSaveContext
+ * instead of throwing an exception.  -1 is returned after an error.
+ */
+int
+ArrayGetNItemsSafe(int ndim, const int *dims, void *escontext)
 {
 	int32		ret;
 	int			i;
@@ -89,7 +99,7 @@ ArrayGetNItems(int ndim, const int *dims)
 
 		/* A negative dimension implies that UB-LB overflowed ... */
 		if (dims[i] < 0)
-			ereport(ERROR,
+			ereturn(escontext, -1,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg("array size exceeds the maximum allowed (%d)",
 							(int) MaxArraySize)));
@@ -98,14 +108,14 @@ ArrayGetNItems(int ndim, const int *dims)
 
 		ret = (int32) prod;
 		if ((int64) ret != prod)
-			ereport(ERROR,
+			ereturn(escontext, -1,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg("array size exceeds the maximum allowed (%d)",
 							(int) MaxArraySize)));
 	}
 	Assert(ret >= 0);
 	if ((Size) ret > MaxArraySize)
-		ereport(ERROR,
+		ereturn(escontext, -1,
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("array size exceeds the maximum allowed (%d)",
 						(int) MaxArraySize)));
@@ -126,6 +136,17 @@ ArrayGetNItems(int ndim, const int *dims)
  */
 void
 ArrayCheckBounds(int ndim, const int *dims, const int *lb)
+{
+	ArrayCheckBoundsSafe(ndim, dims, lb, NULL);
+}
+
+/*
+ * This entry point can return the error into an ErrorSaveContext
+ * instead of throwing an exception.
+ */
+void
+ArrayCheckBoundsSafe(int ndim, const int *dims, const int *lb,
+					 void *escontext)
 {
 	int			i;
 
@@ -135,7 +156,7 @@ ArrayCheckBounds(int ndim, const int *dims, const int *lb)
 		int32		sum PG_USED_FOR_ASSERTS_ONLY;
 
 		if (pg_add_s32_overflow(dims[i], lb[i], &sum))
-			ereport(ERROR,
+			ereturn(escontext,,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg("array lower bound is too large: %d",
 							lb[i])));
diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c
index cd7335287f..e291672ae4 100644
--- a/src/backend/utils/adt/bool.c
+++ b/src/backend/utils/adt/bool.c
@@ -148,13 +148,10 @@ boolin(PG_FUNCTION_ARGS)
 	if (parse_bool_with_len(str, len, &result))
 		PG_RETURN_BOOL(result);
 
-	ereport(ERROR,
+	ereturn(fcinfo->context, (Datum) 0,
 			(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 			 errmsg("invalid input syntax for type %s: \"%s\"",
 					"boolean", in_str)));
-
-	/* not reached */
-	PG_RETURN_BOOL(false);
 }
 
 /*
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 42ddae99ef..e1837bee71 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -291,7 +291,7 @@ int4in(PG_FUNCTION_ARGS)
 {
 	char	   *num = PG_GETARG_CSTRING(0);
 
-	PG_RETURN_INT32(pg_strtoint32(num));
+	PG_RETURN_INT32(pg_strtoint32_safe(num, fcinfo->context));
 }
 
 /*
diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c
index a64422c8d0..0de0bed0e8 100644
--- a/src/backend/utils/adt/numutils.c
+++ b/src/backend/utils/adt/numutils.c
@@ -166,8 +166,11 @@ invalid_syntax:
 /*
  * Convert input string to a signed 32 bit integer.
  *
- * Allows any number of leading or trailing whitespace characters. Will throw
- * ereport() upon bad input format or overflow.
+ * Allows any number of leading or trailing whitespace characters.
+ *
+ * pg_strtoint32() will throw ereport() upon bad input format or overflow;
+ * while pg_strtoint32_safe() instead returns such complaints in *escontext,
+ * if it's an ErrorSaveContext.
  *
  * NB: Accumulate input as an unsigned number, to deal with two's complement
  * representation of the most negative number, which can't be represented as a
@@ -175,6 +178,12 @@ invalid_syntax:
  */
 int32
 pg_strtoint32(const char *s)
+{
+	return pg_strtoint32_safe(s, NULL);
+}
+
+int32
+pg_strtoint32_safe(const char *s, Node *escontext)
 {
 	const char *ptr = s;
 	uint32		tmp = 0;
@@ -227,18 +236,16 @@ pg_strtoint32(const char *s)
 	return (int32) tmp;
 
 out_of_range:
-	ereport(ERROR,
+	ereturn(escontext, 0,
 			(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 			 errmsg("value \"%s\" is out of range for type %s",
 					s, "integer")));
 
 invalid_syntax:
-	ereport(ERROR,
+	ereturn(escontext, 0,
 			(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 			 errmsg("invalid input syntax for type %s: \"%s\"",
 					"integer", s)));
-
-	return 0;					/* keep compiler quiet */
 }
 
 /*
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index db843a0fbf..221362ddb8 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -23,6 +23,7 @@
 #include "funcapi.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
+#include "nodes/miscnodes.h"
 #include "utils/builtins.h"
 #include "utils/datum.h"
 #include "utils/lsyscache.h"
@@ -77,6 +78,7 @@ record_in(PG_FUNCTION_ARGS)
 	char	   *string = PG_GETARG_CSTRING(0);
 	Oid			tupType = PG_GETARG_OID(1);
 	int32		tupTypmod = PG_GETARG_INT32(2);
+	void	   *escontext = fcinfo->context;
 	HeapTupleHeader result;
 	TupleDesc	tupdesc;
 	HeapTuple	tuple;
@@ -100,7 +102,7 @@ record_in(PG_FUNCTION_ARGS)
 	 * supply a valid typmod, and then we can do something useful for RECORD.
 	 */
 	if (tupType == RECORDOID && tupTypmod < 0)
-		ereport(ERROR,
+		ereturn(escontext, (Datum) 0,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("input of anonymous composite types is not implemented")));
 
@@ -152,7 +154,7 @@ record_in(PG_FUNCTION_ARGS)
 	while (*ptr && isspace((unsigned char) *ptr))
 		ptr++;
 	if (*ptr++ != '(')
-		ereport(ERROR,
+		ereturn(escontext, (Datum) 0,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed record literal: \"%s\"", string),
 				 errdetail("Missing left parenthesis.")));
@@ -181,7 +183,7 @@ record_in(PG_FUNCTION_ARGS)
 				ptr++;
 			else
 				/* *ptr must be ')' */
-				ereport(ERROR,
+				ereturn(escontext, (Datum) 0,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("malformed record literal: \"%s\"", string),
 						 errdetail("Too few columns.")));
@@ -204,7 +206,7 @@ record_in(PG_FUNCTION_ARGS)
 				char		ch = *ptr++;
 
 				if (ch == '\0')
-					ereport(ERROR,
+					ereturn(escontext, (Datum) 0,
 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 							 errmsg("malformed record literal: \"%s\"",
 									string),
@@ -212,7 +214,7 @@ record_in(PG_FUNCTION_ARGS)
 				if (ch == '\\')
 				{
 					if (*ptr == '\0')
-						ereport(ERROR,
+						ereturn(escontext, (Datum) 0,
 								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 								 errmsg("malformed record literal: \"%s\"",
 										string),
@@ -252,10 +254,13 @@ record_in(PG_FUNCTION_ARGS)
 			column_info->column_type = column_type;
 		}
 
-		values[i] = InputFunctionCall(&column_info->proc,
-									  column_data,
-									  column_info->typioparam,
-									  att->atttypmod);
+		values[i] = InputFunctionCallSafe(&column_info->proc,
+										  column_data,
+										  column_info->typioparam,
+										  att->atttypmod,
+										  escontext);
+		if (SAFE_ERROR_OCCURRED(escontext))
+			PG_RETURN_NULL();
 
 		/*
 		 * Prep for next column
@@ -264,7 +269,7 @@ record_in(PG_FUNCTION_ARGS)
 	}
 
 	if (*ptr++ != ')')
-		ereport(ERROR,
+		ereturn(escontext, (Datum) 0,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed record literal: \"%s\"", string),
 				 errdetail("Too many columns.")));
@@ -272,7 +277,7 @@ record_in(PG_FUNCTION_ARGS)
 	while (*ptr && isspace((unsigned char) *ptr))
 		ptr++;
 	if (*ptr)
-		ereport(ERROR,
+		ereturn(escontext, (Datum) 0,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed record literal: \"%s\"", string),
 				 errdetail("Junk after right parenthesis.")));
diff --git a/src/include/utils/array.h b/src/include/utils/array.h
index 2f794d1168..c56b6937b0 100644
--- a/src/include/utils/array.h
+++ b/src/include/utils/array.h
@@ -447,7 +447,10 @@ extern void array_free_iterator(ArrayIterator iterator);
 extern int	ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx);
 extern int	ArrayGetOffset0(int n, const int *tup, const int *scale);
 extern int	ArrayGetNItems(int ndim, const int *dims);
+extern int	ArrayGetNItemsSafe(int ndim, const int *dims, void *escontext);
 extern void ArrayCheckBounds(int ndim, const int *dims, const int *lb);
+extern void ArrayCheckBoundsSafe(int ndim, const int *dims, const int *lb,
+								 void *escontext);
 extern void mda_get_range(int n, int *span, const int *st, const int *endp);
 extern void mda_get_prod(int n, const int *range, int *prod);
 extern void mda_get_offset_values(int n, int *dist, const int *prod, const int *span);
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 81631f1645..fbfd8375e3 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -45,6 +45,7 @@ extern int	namestrcmp(Name name, const char *str);
 /* numutils.c */
 extern int16 pg_strtoint16(const char *s);
 extern int32 pg_strtoint32(const char *s);
+extern int32 pg_strtoint32_safe(const char *s, Node *escontext);
 extern int64 pg_strtoint64(const char *s);
 extern int	pg_itoa(int16 i, char *a);
 extern int	pg_ultoa_n(uint32 value, char *a);
