From d807c7ef3f1a04026c3c4b5b24954f7fc84d0e46 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut 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 d38c9fb1a3..c23680f11b 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 597ba4f713..5137834efb 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, "\"."))); 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 b765ff88d6..4d98f17912 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 9ebef1404b..c0ec868bf8 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 +------------- + +(1 row) + SELECT xmlroot(xml '', 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 662c0e236a..5a1a6ac031 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 '', version no value, standalone no value); ERROR: no XML support in this installation SELECT xmlroot(xml '', version '2.0'); diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql index cf96beab06..ae7d633c1c 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 '', version no value, standalone no value); SELECT xmlroot(xml '', version '2.0');