From 7b37918f53dce1cc8cafc473f9d253590a9295ba Mon Sep 17 00:00:00 2001
From: Amul Sul <amul.sul@enterprisedb.com>
Date: Tue, 13 Dec 2022 16:28:30 +0530
Subject: [PATCH v1 08/14] Change circle_in to allow non-throw error reporting

---
 src/backend/utils/adt/geo_ops.c        | 30 +++++++++++++++-----------
 src/test/regress/expected/geometry.out | 25 +++++++++++++++++++++
 src/test/regress/sql/geometry.sql      |  6 ++++++
 3 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 5655f2f64cd..cf4246214a5 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -132,7 +132,8 @@ static float8 dist_ppoly_internal(Point *pt, POLYGON *poly);
 
 /* Routines for encoding and decoding */
 static float8 single_decode(char *num, char **endptr_p,
-							const char *type_name, const char *orig_string);
+							const char *type_name, const char *orig_string,
+							Node *escontext);
 static void single_encode(float8 x, StringInfo str);
 static bool pair_decode(char *str, float8 *x, float8 *y, char **endptr_p,
 						const char *type_name, const char *orig_string,
@@ -190,9 +191,9 @@ static char *path_encode(enum path_delim path_delim, int npts, Point *pt);
 
 static float8
 single_decode(char *num, char **endptr_p,
-			  const char *type_name, const char *orig_string)
+			  const char *type_name, const char *orig_string, Node *escontext)
 {
-	return float8in_internal(num, endptr_p, type_name, orig_string, NULL);
+	return float8in_internal(num, endptr_p, type_name, orig_string, escontext);
 }								/* single_decode() */
 
 static void
@@ -954,13 +955,13 @@ static bool
 line_decode(char *s, const char *str, LINE *line)
 {
 	/* s was already advanced over leading '{' */
-	line->A = single_decode(s, &s, "line", str);
+	line->A = single_decode(s, &s, "line", str, NULL);
 	if (*s++ != DELIM)
 		return false;
-	line->B = single_decode(s, &s, "line", str);
+	line->B = single_decode(s, &s, "line", str, NULL);
 	if (*s++ != DELIM)
 		return false;
-	line->C = single_decode(s, &s, "line", str);
+	line->C = single_decode(s, &s, "line", str, NULL);
 	if (*s++ != RDELIM_L)
 		return false;
 	while (isspace((unsigned char) *s))
@@ -4591,6 +4592,7 @@ Datum
 circle_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
+	Node	   *escontext = fcinfo->context;
 	CIRCLE	   *circle = (CIRCLE *) palloc(sizeof(CIRCLE));
 	char	   *s,
 			   *cp;
@@ -4612,16 +4614,20 @@ circle_in(PG_FUNCTION_ARGS)
 	}
 
 	/* pair_decode will consume parens around the pair, if any */
-	pair_decode(s, &circle->center.x, &circle->center.y, &s, "circle", str,
-				NULL);
+	if (!pair_decode(s, &circle->center.x, &circle->center.y, &s, "circle", str,
+					 escontext))
+		PG_RETURN_NULL();
 
 	if (*s == DELIM)
 		s++;
 
-	circle->radius = single_decode(s, &s, "circle", str);
+	circle->radius = single_decode(s, &s, "circle", str, escontext);
+	if (SOFT_ERROR_OCCURRED(escontext))
+		PG_RETURN_NULL();
+
 	/* We have to accept NaN. */
 	if (circle->radius < 0.0)
-		ereport(ERROR,
+		ereturn(escontext, (Datum) 0,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"circle", str)));
@@ -4636,14 +4642,14 @@ circle_in(PG_FUNCTION_ARGS)
 				s++;
 		}
 		else
-			ereport(ERROR,
+			ereturn(escontext, (Datum) 0,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
 							"circle", str)));
 	}
 
 	if (*s != '\0')
-		ereport(ERROR,
+		ereturn(escontext, (Datum) 0,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"circle", str)));
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index b50103b2165..291cacdf4fb 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -5295,3 +5295,28 @@ SELECT * FROM polygon_tbl WHERE f1 @> '((1,1),(2,2),(2,1))'::polygon
  ((2,0),(2,4),(0,0))
 (1 row)
 
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('(1', 'circle');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('1,', 'circle');
+           pg_input_error_message           
+--------------------------------------------
+ invalid input syntax for type circle: "1,"
+(1 row)
+
+SELECT pg_input_is_valid('(1,2),-1', 'circle');
+ pg_input_is_valid 
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('(1,2),-1', 'circle');
+              pg_input_error_message              
+--------------------------------------------------
+ invalid input syntax for type circle: "(1,2),-1"
+(1 row)
+
diff --git a/src/test/regress/sql/geometry.sql b/src/test/regress/sql/geometry.sql
index 8928d04aa3f..309234b76c1 100644
--- a/src/test/regress/sql/geometry.sql
+++ b/src/test/regress/sql/geometry.sql
@@ -523,3 +523,9 @@ SELECT * FROM polygon_tbl WHERE f1 @> '((1,1),(2,2),(2,1))'::polygon
     ORDER BY (poly_center(f1))[0];
 SELECT * FROM polygon_tbl WHERE f1 @> '((1,1),(2,2),(2,1))'::polygon
     ORDER BY (poly_center(f1))[0];
+
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('(1', 'circle');
+SELECT pg_input_error_message('1,', 'circle');
+SELECT pg_input_is_valid('(1,2),-1', 'circle');
+SELECT pg_input_error_message('(1,2),-1', 'circle');
-- 
2.18.0

