From 4199c297a37a256eec3946c3a4992606884ba105 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Mon, 24 Nov 2025 12:52:16 +0800
Subject: [PATCH v16 03/23] error safe for casting character to other types per
 pg_cast

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

 castsource |    casttarget     | castfunc | castcontext | castmethod |   prosrc    | proname
------------+-------------------+----------+-------------+------------+-------------+---------
 character  | text              |      401 | i           | f          | rtrim1      | text
 character  | character varying |      401 | i           | f          | rtrim1      | text
 character  | "char"            |      944 | a           | f          | text_char   | char
 character  | name              |      409 | i           | f          | bpchar_name | name
 character  | xml               |     2896 | e           | f          | texttoxml   | xml
 character  | character         |      668 | i           | f          | bpchar      | bpchar
(6 rows)

only texttoxml, bpchar(PG_FUNCTION_ARGS) need take care of error handling.
other functions already error safe.

discussion: https://postgr.es/m/CADkLM=fv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ@mail.gmail.com
---
 src/backend/executor/execExprInterp.c |  2 +-
 src/backend/utils/adt/varchar.c       |  2 +-
 src/backend/utils/adt/xml.c           | 18 ++++++++++++------
 src/include/utils/xml.h               |  2 +-
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 5e7bd933afc..1d88cdd2cb4 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -4542,7 +4542,7 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
 
 				*op->resvalue = PointerGetDatum(xmlparse(data,
 														 xexpr->xmloption,
-														 preserve_whitespace));
+														 preserve_whitespace, NULL));
 				*op->resnull = false;
 			}
 			break;
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index 39fc27e1f11..8618c7a1b13 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -307,7 +307,7 @@ bpchar(PG_FUNCTION_ARGS)
 		{
 			for (i = maxmblen; i < len; i++)
 				if (s[i] != ' ')
-					ereport(ERROR,
+					ereturn(fcinfo->context, (Datum) 0,
 							(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 							 errmsg("value too long for type character(%d)",
 									maxlen)));
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index c8ab9d61c68..6301115d625 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -659,7 +659,7 @@ texttoxml(PG_FUNCTION_ARGS)
 {
 	text	   *data = PG_GETARG_TEXT_PP(0);
 
-	PG_RETURN_XML_P(xmlparse(data, xmloption, true));
+	PG_RETURN_XML_P(xmlparse(data, xmloption, true, fcinfo->context));
 }
 
 
@@ -1028,19 +1028,25 @@ xmlelement(XmlExpr *xexpr,
 
 
 xmltype *
-xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace)
+xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, Node *escontext)
 {
 #ifdef USE_LIBXML
 	xmlDocPtr	doc;
 
 	doc = xml_parse(data, xmloption_arg, preserve_whitespace,
-					GetDatabaseEncoding(), NULL, NULL, NULL);
-	xmlFreeDoc(doc);
+					GetDatabaseEncoding(), NULL, NULL, escontext);
+	if (doc)
+		xmlFreeDoc(doc);
+
+	if (SOFT_ERROR_OCCURRED(escontext))
+		return NULL;
 
 	return (xmltype *) data;
 #else
-	NO_XML_SUPPORT();
-	return NULL;
+	ereturn(escontext, NULL
+			errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			errmsg("unsupported XML feature"),
+			errdetail("This functionality requires the server to be built with libxml support."));
 #endif
 }
 
diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h
index 732dac47bc4..b15168c430e 100644
--- a/src/include/utils/xml.h
+++ b/src/include/utils/xml.h
@@ -73,7 +73,7 @@ extern xmltype *xmlconcat(List *args);
 extern xmltype *xmlelement(XmlExpr *xexpr,
 						   const Datum *named_argvalue, const bool *named_argnull,
 						   const Datum *argvalue, const bool *argnull);
-extern xmltype *xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace);
+extern xmltype *xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, Node *escontext);
 extern xmltype *xmlpi(const char *target, text *arg, bool arg_is_null, bool *result_is_null);
 extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
 extern bool xml_is_document(xmltype *arg);
-- 
2.34.1

