From c671eb6bf8b5d0b12dd9150ec68fd6291a1d23d0 Mon Sep 17 00:00:00 2001
From: Amul Sul <amul.sul@enterprisedb.com>
Date: Wed, 14 Dec 2022 10:49:53 +0530
Subject: [PATCH v1 15/25] Change oidin and oidvectorin to allow non-throw
 error reporting

---
 src/backend/utils/adt/oid.c       | 24 ++++++++-------
 src/test/regress/expected/oid.out | 49 +++++++++++++++++++++++++++++++
 src/test/regress/sql/oid.sql      | 11 +++++++
 3 files changed, 74 insertions(+), 10 deletions(-)

diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index b5af4223412..0bc2d662258 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -19,6 +19,7 @@
 
 #include "catalog/pg_type.h"
 #include "libpq/pqformat.h"
+#include "nodes/miscnodes.h"
 #include "nodes/value.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
@@ -32,14 +33,14 @@
  *****************************************************************************/
 
 static Oid
-oidin_subr(const char *s, char **endloc)
+oidin_subr(const char *s, char **endloc, Node *escontext)
 {
 	unsigned long cvt;
 	char	   *endptr;
 	Oid			result;
 
 	if (*s == '\0')
-		ereport(ERROR,
+		ereturn(escontext, InvalidOid,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"oid", s)));
@@ -53,19 +54,19 @@ oidin_subr(const char *s, char **endloc)
 	 * handled by the second "if" consistent across platforms.
 	 */
 	if (errno && errno != ERANGE && errno != EINVAL)
-		ereport(ERROR,
+		ereturn(escontext, InvalidOid,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"oid", s)));
 
 	if (endptr == s && *s != '\0')
-		ereport(ERROR,
+		ereturn(escontext, InvalidOid,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"oid", s)));
 
 	if (errno == ERANGE)
-		ereport(ERROR,
+		ereturn(escontext, InvalidOid,
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("value \"%s\" is out of range for type %s",
 						s, "oid")));
@@ -81,7 +82,7 @@ oidin_subr(const char *s, char **endloc)
 		while (*endptr && isspace((unsigned char) *endptr))
 			endptr++;
 		if (*endptr)
-			ereport(ERROR,
+			ereturn(escontext, InvalidOid,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
 							"oid", s)));
@@ -104,7 +105,7 @@ oidin_subr(const char *s, char **endloc)
 #if OID_MAX != ULONG_MAX
 	if (cvt != (unsigned long) result &&
 		cvt != (unsigned long) ((int) result))
-		ereport(ERROR,
+		ereturn(escontext, InvalidOid,
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("value \"%s\" is out of range for type %s",
 						s, "oid")));
@@ -119,7 +120,7 @@ oidin(PG_FUNCTION_ARGS)
 	char	   *s = PG_GETARG_CSTRING(0);
 	Oid			result;
 
-	result = oidin_subr(s, NULL);
+	result = oidin_subr(s, NULL, fcinfo->context);
 	PG_RETURN_OID(result);
 }
 
@@ -194,6 +195,7 @@ Datum
 oidvectorin(PG_FUNCTION_ARGS)
 {
 	char	   *oidString = PG_GETARG_CSTRING(0);
+	Node	   *escontext = fcinfo->context;
 	oidvector  *result;
 	int			n;
 
@@ -205,7 +207,9 @@ oidvectorin(PG_FUNCTION_ARGS)
 			oidString++;
 		if (*oidString == '\0')
 			break;
-		result->values[n] = oidin_subr(oidString, &oidString);
+		result->values[n] = oidin_subr(oidString, &oidString, escontext);
+		if (SOFT_ERROR_OCCURRED(escontext))
+			PG_RETURN_NULL();
 	}
 	while (*oidString && isspace((unsigned char) *oidString))
 		oidString++;
@@ -324,7 +328,7 @@ oidparse(Node *node)
 			 * constants by the lexer.  Accept these if they are valid OID
 			 * strings.
 			 */
-			return oidin_subr(castNode(Float, node)->fval, NULL);
+			return oidin_subr(castNode(Float, node)->fval, NULL, NULL);
 		default:
 			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
 	}
diff --git a/src/test/regress/expected/oid.out b/src/test/regress/expected/oid.out
index 89093734536..b9687aef00c 100644
--- a/src/test/regress/expected/oid.out
+++ b/src/test/regress/expected/oid.out
@@ -120,3 +120,52 @@ SELECT o.* FROM OID_TBL o WHERE o.f1 > '1234';
 (3 rows)
 
 DROP TABLE OID_TBL;
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('01XYZ', 'oid');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('01XYZ', 'oid');
+           pg_input_error_message           
+--------------------------------------------
+ invalid input syntax for type oid: "01XYZ"
+(1 row)
+
+SELECT pg_input_is_valid('9999999999', 'oid');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('9999999999', 'oid');
+             pg_input_error_message              
+-------------------------------------------------
+ value "9999999999" is out of range for type oid
+(1 row)
+
+SELECT pg_input_is_valid('01 01XYZ', 'oidvector');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('01 01XYZ', 'oidvector');
+          pg_input_error_message          
+------------------------------------------
+ invalid input syntax for type oid: "XYZ"
+(1 row)
+
+SELECT pg_input_is_valid('01 9999999999', 'oidvector');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('01 9999999999', 'oidvector');
+             pg_input_error_message              
+-------------------------------------------------
+ value "9999999999" is out of range for type oid
+(1 row)
+
diff --git a/src/test/regress/sql/oid.sql b/src/test/regress/sql/oid.sql
index 25b4b68a6a0..8c657908351 100644
--- a/src/test/regress/sql/oid.sql
+++ b/src/test/regress/sql/oid.sql
@@ -41,3 +41,14 @@ SELECT o.* FROM OID_TBL o WHERE o.f1 >= '1234';
 SELECT o.* FROM OID_TBL o WHERE o.f1 > '1234';
 
 DROP TABLE OID_TBL;
+
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('01XYZ', 'oid');
+SELECT pg_input_error_message('01XYZ', 'oid');
+SELECT pg_input_is_valid('9999999999', 'oid');
+SELECT pg_input_error_message('9999999999', 'oid');
+
+SELECT pg_input_is_valid('01 01XYZ', 'oidvector');
+SELECT pg_input_error_message('01 01XYZ', 'oidvector');
+SELECT pg_input_is_valid('01 9999999999', 'oidvector');
+SELECT pg_input_error_message('01 9999999999', 'oidvector');
-- 
2.18.0

