From d807c7ef3f1a04026c3c4b5b24954f7fc84d0e46 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Sun, 7 Jan 2007 22:49:56 +0000
Subject: [PATCH] Some fine-tuning of xmlpi in corner cases: - correct error
 codes - do syntax checks in correct order - strip leading spaces of argument

---
 src/backend/executor/execQual.c     | 14 ++++++++------
 src/backend/utils/adt/xml.c         | 16 ++++++++++++----
 src/include/utils/xml.h             |  4 ++--
 src/test/regress/expected/xml.out   | 15 +++++++++++++++
 src/test/regress/expected/xml_1.out |  6 ++++++
 src/test/regress/sql/xml.sql        |  3 +++
 6 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index d38c9fb1a37..c23680f11be 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.203 2007/01/05 22:19:27 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.204 2007/01/07 22:49:55 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2803,15 +2803,17 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 					e = (ExprState *) linitial(xmlExpr->args);
 					value = ExecEvalExpr(e, econtext, &isnull, NULL);
 					if (isnull)
-						return (Datum) 0;
-					arg = DatumGetTextP(value);
+						arg = NULL;
+					else
+						arg = DatumGetTextP(value);
 				}
 				else
+				{
 					arg = NULL;
+					isnull = false;
+				}
 
-				*isNull = false;
-
-				return PointerGetDatum(xmlpi(xexpr->name, arg));
+				return PointerGetDatum(xmlpi(xexpr->name, arg, isnull, isNull));
 			}
 			break;
 
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 597ba4f7137..5137834efb1 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.12 2007/01/07 00:13:55 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.13 2007/01/07 22:49:56 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -257,7 +257,7 @@ xmlparse(text *data, bool is_document, bool preserve_whitespace)
 
 
 xmltype *
-xmlpi(char *target, text *arg)
+xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null)
 {
 #ifdef USE_LIBXML
 	xmltype *result;
@@ -265,10 +265,18 @@ xmlpi(char *target, text *arg)
 
 	if (pg_strncasecmp(target, "xml", 3) == 0)
 		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
+				(errcode(ERRCODE_SYNTAX_ERROR),	/* really */
 				 errmsg("invalid XML processing instruction"),
 				 errdetail("XML processing instruction target name cannot start with \"xml\".")));
 
+	/*
+	 * Following the SQL standard, the null check comes after the
+	 * syntax check above.
+	 */
+	*result_is_null = arg_is_null;
+	if (*result_is_null)
+		return NULL;		
+
 	initStringInfo(&buf);
 
 	appendStringInfo(&buf, "<?%s", target);
@@ -286,7 +294,7 @@ xmlpi(char *target, text *arg)
 				 errdetail("XML processing instruction cannot contain \"?>\".")));
 
 		appendStringInfoChar(&buf, ' ');
-		appendStringInfoString(&buf, string);
+		appendStringInfoString(&buf, string + strspn(string, " "));
 		pfree(string);
 	}
 	appendStringInfoString(&buf, "?>");
diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h
index b765ff88d67..4d98f179124 100644
--- a/src/include/utils/xml.h
+++ b/src/include/utils/xml.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.6 2007/01/05 22:20:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.7 2007/01/07 22:49:56 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,7 +33,7 @@ extern Datum texttoxml(PG_FUNCTION_ARGS);
 extern Datum xmlvalidate(PG_FUNCTION_ARGS);
 
 extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
-extern xmltype *xmlpi(char *target, text *arg);
+extern xmltype *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null);
 extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
 
 extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped);
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index 9ebef1404b9..c0ec868bf89 100644
--- a/src/test/regress/expected/xml.out
+++ b/src/test/regress/expected/xml.out
@@ -124,6 +124,21 @@ SELECT xmlpi(name foo, 'bar');
 SELECT xmlpi(name foo, 'in?>valid');
 ERROR:  invalid XML processing instruction
 DETAIL:  XML processing instruction cannot contain "?>".
+SELECT xmlpi(name foo, null);
+ xmlpi 
+-------
+ 
+(1 row)
+
+SELECT xmlpi(name xmlstuff, null);
+ERROR:  invalid XML processing instruction
+DETAIL:  XML processing instruction target name cannot start with "xml".
+SELECT xmlpi(name foo, '   bar');
+    xmlpi    
+-------------
+ <?foo bar?>
+(1 row)
+
 SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
         xmlroot        
 -----------------------
diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out
index 662c0e236a8..5a1a6ac0319 100644
--- a/src/test/regress/expected/xml_1.out
+++ b/src/test/regress/expected/xml_1.out
@@ -62,6 +62,12 @@ SELECT xmlpi(name foo, 'bar');
 ERROR:  no XML support in this installation
 SELECT xmlpi(name foo, 'in?>valid');
 ERROR:  no XML support in this installation
+SELECT xmlpi(name foo, null);
+ERROR:  no XML support in this installation
+SELECT xmlpi(name xmlstuff, null);
+ERROR:  no XML support in this installation
+SELECT xmlpi(name foo, '   bar');
+ERROR:  no XML support in this installation
 SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
 ERROR:  no XML support in this installation
 SELECT xmlroot(xml '<foo/>', version '2.0');
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index cf96beab060..ae7d633c1c4 100644
--- a/src/test/regress/sql/xml.sql
+++ b/src/test/regress/sql/xml.sql
@@ -51,6 +51,9 @@ SELECT xmlpi(name foo);
 SELECT xmlpi(name xmlstuff);
 SELECT xmlpi(name foo, 'bar');
 SELECT xmlpi(name foo, 'in?>valid');
+SELECT xmlpi(name foo, null);
+SELECT xmlpi(name xmlstuff, null);
+SELECT xmlpi(name foo, '   bar');
 
 SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
 SELECT xmlroot(xml '<foo/>', version '2.0');
-- 
GitLab