Code review for XML patch. Instill a bit of sanity in the location of
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 24 Dec 2006 00:29:20 +0000 (00:29 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 24 Dec 2006 00:29:20 +0000 (00:29 +0000)
the XmlExpr code in various lists, use a representation that has some hope
of reverse-listing correctly (though it's still a de-escaping function
shy of correctness), generally try to make it look more like Postgres
coding conventions.

27 files changed:
doc/src/sgml/errcodes.sgml
doc/src/sgml/installation.sgml
src/backend/executor/execQual.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/util/clauses.c
src/backend/parser/gram.y
src/backend/parser/keywords.c
src/backend/parser/parse_clause.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_target.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/xml.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/nodes/execnodes.h
src/include/nodes/nodes.h
src/include/nodes/primnodes.h
src/include/parser/parse_coerce.h
src/include/utils/xml.h
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/plerrcodes.h
src/test/regress/expected/opr_sanity.out
src/test/regress/sql/opr_sanity.sql

index bf06cfaf5e5874d6f821c54acff1e8f51d0ae1d6..ced6197d978527fefb601f3cb9f6e0bedcd60eea 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.20 2006/06/16 23:29:26 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.21 2006/12/24 00:29:17 tgl Exp $ -->
 
 <appendix id="errcodes-appendix">
  <title><productname>PostgreSQL</productname> Error Codes</title>
 <entry>untranslatable_character</entry>
 </row>
 
+<row>
+<entry><literal>2200M</literal></entry>
+<entry>INVALID XML DOCUMENT</entry>
+<entry>invalid_xml_document</entry>
+</row>
+
+<row>
+<entry><literal>2200N</literal></entry>
+<entry>INVALID XML CONTENT</entry>
+<entry>invalid_xml_content</entry>
+</row>
+
+<row>
+<entry><literal>2200S</literal></entry>
+<entry>INVALID XML COMMENT</entry>
+<entry>invalid_xml_comment</entry>
+</row>
+
+<row>
+<entry><literal>2200T</literal></entry>
+<entry>INVALID XML PROCESSING INSTRUCTION</entry>
+<entry>invalid_xml_processing_instruction</entry>
+</row>
 
 <row>
 <entry spanname="span13"><emphasis role="bold">Class 23 &mdash; Integrity Constraint Violation</></entry>
index a56ba9ad9b8461c2fe02f34e61b2d8e86fc536dc..3119671fc4be7f443c38f8ecd6164b00e49317fa 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.269 2006/12/21 16:05:13 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.270 2006/12/24 00:29:17 tgl Exp $ -->
 
 <chapter id="installation">
  <title><![%standalone-include[<productname>PostgreSQL</>]]>
@@ -909,7 +909,7 @@ su - postgres
        <term><option>--with-libxml</option></term>
        <listitem>
         <para>
-         Build with libxml, required for SQL/XML support.
+         Build with libxml (enables SQL/XML support).
         </para>
        </listitem>
       </varlistentry>
index 1e9865c300755d6c3998eb12d15a62d0b66f67c7..145da9b46368d67b3f98f50c19bbf5bd0664aaf3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.201 2006/12/23 00:43:09 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.202 2006/12/24 00:29:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -117,11 +117,11 @@ static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
 static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
               ExprContext *econtext,
               bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
+                        bool *isNull, ExprDoneCond *isDone);
 static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
               ExprContext *econtext,
               bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
-                        bool *isNull, ExprDoneCond *isDone);
 static Datum ExecEvalNullTest(NullTestState *nstate,
                 ExprContext *econtext,
                 bool *isNull, ExprDoneCond *isDone);
@@ -2638,6 +2638,237 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
    return result;
 }
 
+/* ----------------------------------------------------------------
+ *     ExecEvalXml
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
+           bool *isNull, ExprDoneCond *isDone)
+{
+   XmlExpr        *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
+   text           *result;
+   StringInfoData  buf;
+   Datum           value;
+   bool            isnull;
+   char           *str;
+   ListCell       *arg;
+   ListCell   *narg;
+   bool    found_arg;
+   int             i;
+
+   if (isDone)
+       *isDone = ExprSingleResult;
+   *isNull = true;             /* until we get a result */
+
+   switch (xexpr->op)
+   {
+       case IS_XMLCONCAT:
+           initStringInfo(&buf);
+           foreach(arg, xmlExpr->args)
+           {
+               ExprState   *e = (ExprState *) lfirst(arg);
+
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (!isnull)
+               {
+                   /* we know the value is XML type */
+                   str = DatumGetCString(DirectFunctionCall1(xml_out,
+                                                             value));
+                   appendStringInfoString(&buf, str);
+                   pfree(str);
+                   *isNull = false;
+               }
+           }
+           break;
+
+       case IS_XMLELEMENT:
+           initStringInfo(&buf);
+           *isNull = false;
+           appendStringInfo(&buf, "<%s", xexpr->name);
+           i = 0;
+           forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
+           {
+               ExprState   *e = (ExprState *) lfirst(arg);
+               char    *argname = strVal(lfirst(narg));
+
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (!isnull)
+               {
+                   str = OutputFunctionCall(&xmlExpr->named_outfuncs[i],
+                                            value);
+                   appendStringInfo(&buf, " %s=\"%s\"", argname, str);
+                   pfree(str);
+               }
+               i++;
+           }
+
+           found_arg = false;
+           foreach(arg, xmlExpr->args)
+           {
+               ExprState   *e = (ExprState *) lfirst(arg);
+
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (!isnull)
+               {
+                   if (!found_arg)
+                   {
+                       appendStringInfoChar(&buf, '>');
+                       found_arg = true;
+                   }
+
+                   /* we know the value is XML type */
+                   str = DatumGetCString(DirectFunctionCall1(xml_out,
+                                                             value));
+                   appendStringInfoString(&buf, str);
+                   pfree(str);
+               }
+           }
+
+           if (!found_arg)
+               appendStringInfo(&buf, "/>");
+           else
+               appendStringInfo(&buf, "</%s>", xexpr->name);
+           break;
+
+       case IS_XMLFOREST:
+           initStringInfo(&buf);
+           i = 0;
+           forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
+           {
+               ExprState   *e = (ExprState *) lfirst(arg);
+               char    *argname = strVal(lfirst(narg));
+
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (!isnull)
+               {
+                   str = OutputFunctionCall(&xmlExpr->named_outfuncs[i],
+                                            value);
+                   appendStringInfo(&buf, "<%s>%s</%s>",
+                                    argname, str, argname);
+                   pfree(str);
+                   *isNull = false;
+               }
+               i++;
+           }
+           break;
+
+           /* The remaining cases don't need to set up buf */
+       case IS_XMLPARSE:
+           {
+               ExprState   *e;
+               text        *data;
+               bool        is_document;
+               bool        preserve_whitespace;
+
+               /* arguments are known to be text, bool, bool */
+               Assert(list_length(xmlExpr->args) == 3);
+
+               e = (ExprState *) linitial(xmlExpr->args);
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (isnull)
+                   return (Datum) 0;
+               data = DatumGetTextP(value);
+
+               e = (ExprState *) lsecond(xmlExpr->args);
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (isnull)     /* probably can't happen */
+                   return (Datum) 0;
+               is_document = DatumGetBool(value);
+
+               e = (ExprState *) lthird(xmlExpr->args);
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (isnull)     /* probably can't happen */
+                   return (Datum) 0;
+               preserve_whitespace = DatumGetBool(value);
+
+               *isNull = false;
+
+               return PointerGetDatum(xmlparse(data,
+                                               is_document,
+                                               preserve_whitespace));
+           }
+           break;
+
+       case IS_XMLPI:
+           {
+               ExprState   *e;
+               text        *arg;
+
+               /* optional argument is known to be text */
+               Assert(list_length(xmlExpr->args) <= 1);
+
+               if (xmlExpr->args)
+               {
+                   e = (ExprState *) linitial(xmlExpr->args);
+                   value = ExecEvalExpr(e, econtext, &isnull, NULL);
+                   if (isnull)
+                       return (Datum) 0;
+                   arg = DatumGetTextP(value);
+               }
+               else
+                   arg = NULL;
+
+               *isNull = false;
+
+               return PointerGetDatum(xmlpi(xexpr->name, arg));
+           }
+           break;
+
+       case IS_XMLROOT:
+           {
+               ExprState   *e;
+               xmltype     *data;
+               text        *version;
+               int         standalone;
+
+               /* arguments are known to be xml, text, bool */
+               Assert(list_length(xmlExpr->args) == 3);
+
+               e = (ExprState *) linitial(xmlExpr->args);
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (isnull)
+                   return (Datum) 0;
+               data = DatumGetXmlP(value);
+
+               e = (ExprState *) lsecond(xmlExpr->args);
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (isnull)
+                   version = NULL;
+               else
+                   version = DatumGetTextP(value);
+
+               e = (ExprState *) lthird(xmlExpr->args);
+               value = ExecEvalExpr(e, econtext, &isnull, NULL);
+               if (isnull)
+                   standalone = 0;
+               else
+                   standalone = (DatumGetBool(value) ? 1 : -1);
+
+               *isNull = false;
+
+               return PointerGetDatum(xmlroot(data,
+                                              version,
+                                              standalone));
+           }
+           break;
+   }
+
+   if (*isNull)
+       result = NULL;
+   else
+   {
+       int     len = buf.len + VARHDRSZ;
+
+       result = palloc(len);
+       VARATT_SIZEP(result) = len;
+       memcpy(VARDATA(result), buf.data, buf.len);
+   }
+
+   pfree(buf.data);
+   return PointerGetDatum(result);
+}
+
 /* ----------------------------------------------------------------
  *     ExecEvalNullIf
  *
@@ -2881,120 +3112,6 @@ ExecEvalBooleanTest(GenericExprState *bstate,
    }
 }
 
-/* ----------------------------------------------------------------
- *     ExecEvalXml
- * ----------------------------------------------------------------
- */
-static Datum
-ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
-           bool *isNull, ExprDoneCond *isDone)
-{
-   StringInfoData  buf;
-   bool            isnull;
-   ListCell       *arg;
-   text           *result = NULL;
-   int             len;
-
-   initStringInfo(&buf);
-
-   *isNull = false;
-
-   if (isDone)
-       *isDone = ExprSingleResult;
-
-   switch (xmlExpr->op)
-   {
-       case IS_XMLCONCAT:
-           *isNull = true;
-
-           foreach(arg, xmlExpr->args)
-           {
-               ExprState   *e = (ExprState *) lfirst(arg);
-               Datum       value = ExecEvalExpr(e, econtext, &isnull, NULL);
-
-               if (!isnull)
-               {
-                   appendStringInfoString(&buf, DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeout, value)));
-                   *isNull = false;
-               }
-           }
-           break;
-
-       case IS_XMLELEMENT:
-           {
-               int state = 0, i = 0;
-               appendStringInfo(&buf, "<%s", xmlExpr->name);
-               foreach(arg, xmlExpr->named_args)
-               {
-                   GenericExprState *gstate = (GenericExprState *) lfirst(arg);
-                   Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
-                   if (!isnull)
-                   {
-                       char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->named_args_tcache[i], value));
-                       appendStringInfo(&buf, " %s=\"%s\"", xmlExpr->named_args_ncache[i], outstr);
-                       pfree(outstr);
-                   }
-                   i++;
-               }
-               if (xmlExpr->args)
-               {
-                   ExprState   *expr = linitial(xmlExpr->args);
-                   Datum       value = ExecEvalExpr(expr, econtext, &isnull, NULL);
-
-                   if (!isnull)
-                   {
-                       char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeout, value));
-                       if (state == 0)
-                       {
-                           appendStringInfoChar(&buf, '>');
-                           state = 1;
-                       }
-                       appendStringInfo(&buf, "%s", outstr);
-                       pfree(outstr);
-                   }
-               }
-
-               if (state == 0)
-                   appendStringInfo(&buf, "/>");
-               else if (state == 1)
-                   appendStringInfo(&buf, "</%s>", xmlExpr->name);     
-
-           }
-           break;
-
-       case IS_XMLFOREST:
-           {
-               /* only if all argumets are null returns null */
-               int i = 0; 
-               *isNull = true;
-               foreach(arg, xmlExpr->named_args)
-               {
-                   GenericExprState *gstate = (GenericExprState *) lfirst(arg);
-                   Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
-                   if (!isnull)
-                   {
-                       char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->named_args_tcache[i], value));
-                       appendStringInfo(&buf, "<%s>%s</%s>", xmlExpr->named_args_ncache[i], outstr, xmlExpr->named_args_ncache[i]);
-                       pfree(outstr);
-                       *isNull = false;
-                   }
-                   i += 1;
-               }       
-           }
-           break;
-       default:
-           break;
-   }
-
-   len = buf.len + VARHDRSZ;
-   result = palloc(len);
-   VARATT_SIZEP(result) = len;
-   memcpy(VARDATA(result), buf.data, buf.len);
-   pfree(buf.data);
-   PG_RETURN_TEXT_P(result);
-}
-
 /*
  * ExecEvalCoerceToDomain
  *
@@ -3794,59 +3911,45 @@ ExecInitExpr(Expr *node, PlanState *parent)
            break;
        case T_XmlExpr:
            {
-               List            *outlist; 
-               ListCell        *arg;
                XmlExpr         *xexpr = (XmlExpr *) node;
                XmlExprState    *xstate = makeNode(XmlExprState);
-               int             i = 0; 
-               Oid             typeout;
-       
-               xstate->name = xexpr->name;
-                               
+               List            *outlist;
+               ListCell        *arg;
+               int             i;
+
                xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml;
-               xstate->op = xexpr->op;
-               
+               xstate->named_outfuncs = (FmgrInfo *)
+                   palloc0(list_length(xexpr->named_args) * sizeof(FmgrInfo));
                outlist = NIL;
-               if (xexpr->named_args)
-               {
-                   xstate->named_args_tcache = (Oid *) palloc(list_length(xexpr->named_args) * sizeof(int));
-                   xstate->named_args_ncache = (char **) palloc(list_length(xexpr->named_args) * sizeof(char *));
-                   
-                   i = 0;
-                   foreach(arg, xexpr->named_args)
-                   {
-                       bool        tpisvarlena;
-                       Expr        *e = (Expr *) lfirst(arg);
-                       ExprState   *estate = ExecInitExpr(e, parent);
-                       TargetEntry *tle;
-                       outlist = lappend(outlist, estate);                 
-                       tle = (TargetEntry *) ((GenericExprState *) estate)->xprstate.expr;
-                       getTypeOutputInfo(exprType((Node *)tle->expr), &typeout, &tpisvarlena);
-                       xstate->named_args_ncache[i] = tle->resname;
-                       xstate->named_args_tcache[i] = typeout;
-                       i++;
-                   }   
-               }
-               else
+               i = 0;
+               foreach(arg, xexpr->named_args)
                {
-                   xstate->named_args_tcache = NULL;
-                   xstate->named_args_ncache = NULL;
+                   Expr        *e = (Expr *) lfirst(arg);
+                   ExprState   *estate;
+                   Oid         typOutFunc;
+                   bool        typIsVarlena;
+
+                   estate = ExecInitExpr(e, parent);
+                   outlist = lappend(outlist, estate);
+
+                   getTypeOutputInfo(exprType((Node *) e),
+                                     &typOutFunc, &typIsVarlena);
+                   fmgr_info(typOutFunc, &xstate->named_outfuncs[i]);
+                   i++;
                }
                xstate->named_args = outlist;
 
-               outlist = NIL;              
+               outlist = NIL;
                foreach(arg, xexpr->args)
                {
-                   bool        tpisvarlena;
-                   ExprState   *estate;
-                   Expr        *e = (Expr *) lfirst(arg);
-                   getTypeOutputInfo(exprType((Node *)e), &typeout, &tpisvarlena);
+                   Expr        *e = (Expr *) lfirst(arg);
+                   ExprState   *estate;
+
                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                }
-               xstate->arg_typeout = typeout;
                xstate->args = outlist;
-               
+
                state = (ExprState *) xstate;
            }
            break;
index ca841cb181aaed174ed03f1aa83970da5198d0b3..d46ed57d830e0b7a85622fd0bb32024bf857701a 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.356 2006/12/23 00:43:09 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.357 2006/12/24 00:29:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1093,6 +1093,23 @@ _copyMinMaxExpr(MinMaxExpr *from)
    return newnode;
 }
 
+/*
+ * _copyXmlExpr
+ */
+static XmlExpr *
+_copyXmlExpr(XmlExpr *from)
+{
+   XmlExpr *newnode = makeNode(XmlExpr);
+
+   COPY_SCALAR_FIELD(op);
+   COPY_STRING_FIELD(name);
+   COPY_NODE_FIELD(named_args);
+   COPY_NODE_FIELD(arg_names);
+   COPY_NODE_FIELD(args);
+
+   return newnode;
+}
+
 /*
  * _copyNullIfExpr (same as OpExpr)
  */
@@ -1138,22 +1155,6 @@ _copyBooleanTest(BooleanTest *from)
    return newnode;
 }
 
-/*
- * _copyXmlExpr
- */
-static XmlExpr *
-_copyXmlExpr(XmlExpr *from)
-{
-   XmlExpr *newnode = makeNode(XmlExpr);
-
-   COPY_SCALAR_FIELD(op);
-   COPY_STRING_FIELD(name);
-   COPY_NODE_FIELD(named_args);
-   COPY_NODE_FIELD(args);
-
-   return newnode;
-}
-
 /*
  * _copyCoerceToDomain
  */
@@ -2977,6 +2978,9 @@ copyObject(void *from)
        case T_MinMaxExpr:
            retval = _copyMinMaxExpr(from);
            break;
+       case T_XmlExpr:
+           retval = _copyXmlExpr(from);
+           break;
        case T_NullIfExpr:
            retval = _copyNullIfExpr(from);
            break;
@@ -2986,9 +2990,6 @@ copyObject(void *from)
        case T_BooleanTest:
            retval = _copyBooleanTest(from);
            break;
-       case T_XmlExpr:
-           retval = _copyXmlExpr(from);
-           break;
        case T_CoerceToDomain:
            retval = _copyCoerceToDomain(from);
            break;
index a7c4ef4e2a819e5838176bf382ff7752088d5bd4..29bff448c7f53ce4387cb401cc66c13aa0876427 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.290 2006/12/23 00:43:10 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.291 2006/12/24 00:29:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -454,6 +454,18 @@ _equalMinMaxExpr(MinMaxExpr *a, MinMaxExpr *b)
    return true;
 }
 
+static bool
+_equalXmlExpr(XmlExpr *a, XmlExpr *b)
+{
+   COMPARE_SCALAR_FIELD(op);
+   COMPARE_STRING_FIELD(name);
+   COMPARE_NODE_FIELD(named_args);
+   COMPARE_NODE_FIELD(arg_names);
+   COMPARE_NODE_FIELD(args);
+
+   return true;
+}
+
 static bool
 _equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
 {
@@ -495,17 +507,6 @@ _equalBooleanTest(BooleanTest *a, BooleanTest *b)
    return true;
 }
 
-static bool
-_equalXmlExpr(XmlExpr *a, XmlExpr *b)
-{
-   COMPARE_SCALAR_FIELD(op);
-   COMPARE_STRING_FIELD(name);
-   COMPARE_NODE_FIELD(named_args);
-   COMPARE_NODE_FIELD(args);
-
-   return true;
-}
-
 static bool
 _equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b)
 {
@@ -1971,6 +1972,9 @@ equal(void *a, void *b)
        case T_MinMaxExpr:
            retval = _equalMinMaxExpr(a, b);
            break;
+       case T_XmlExpr:
+           retval = _equalXmlExpr(a, b);
+           break;
        case T_NullIfExpr:
            retval = _equalNullIfExpr(a, b);
            break;
@@ -1980,9 +1984,6 @@ equal(void *a, void *b)
        case T_BooleanTest:
            retval = _equalBooleanTest(a, b);
            break;
-       case T_XmlExpr:
-           retval = _equalXmlExpr(a, b);
-           break;
        case T_CoerceToDomain:
            retval = _equalCoerceToDomain(a, b);
            break;
index b18b6988cfa776163141f877c8b570eaf6ae52c5..4911d6ed4044c33a197fe268836e5847783c213c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.288 2006/12/23 00:43:10 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.289 2006/12/24 00:29:18 tgl Exp $
  *
  * NOTES
  *   Every node type that can appear in stored rules' parsetrees *must*
@@ -892,6 +892,18 @@ _outMinMaxExpr(StringInfo str, MinMaxExpr *node)
    WRITE_NODE_FIELD(args);
 }
 
+static void
+_outXmlExpr(StringInfo str, XmlExpr *node)
+{
+   WRITE_NODE_TYPE("XMLEXPR");
+   
+   WRITE_ENUM_FIELD(op, XmlExprOp);
+   WRITE_STRING_FIELD(name);
+   WRITE_NODE_FIELD(named_args);
+   WRITE_NODE_FIELD(arg_names);
+   WRITE_NODE_FIELD(args);
+}
+
 static void
 _outNullIfExpr(StringInfo str, NullIfExpr *node)
 {
@@ -922,17 +934,6 @@ _outBooleanTest(StringInfo str, BooleanTest *node)
    WRITE_ENUM_FIELD(booltesttype, BoolTestType);
 }
 
-static void
-_outXmlExpr(StringInfo str, XmlExpr *node)
-{
-   WRITE_NODE_TYPE("XMLEXPR");
-   
-   WRITE_ENUM_FIELD(op, XmlExprOp);
-   WRITE_STRING_FIELD(name);
-   WRITE_NODE_FIELD(named_args);
-   WRITE_NODE_FIELD(args);
-}
-
 static void
 _outCoerceToDomain(StringInfo str, CoerceToDomain *node)
 {
@@ -2026,6 +2027,9 @@ _outNode(StringInfo str, void *obj)
            case T_MinMaxExpr:
                _outMinMaxExpr(str, obj);
                break;
+           case T_XmlExpr:
+               _outXmlExpr(str, obj);
+               break;
            case T_NullIfExpr:
                _outNullIfExpr(str, obj);
                break;
@@ -2035,9 +2039,6 @@ _outNode(StringInfo str, void *obj)
            case T_BooleanTest:
                _outBooleanTest(str, obj);
                break;
-           case T_XmlExpr:
-               _outXmlExpr(str, obj);
-               break;
            case T_CoerceToDomain:
                _outCoerceToDomain(str, obj);
                break;
index 37b39439eb0d4f69066b5c5525f0497d654e38cb..781eeee14f16727414f863e12b051a74dd4d9d83 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.198 2006/12/23 00:43:10 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.199 2006/12/24 00:29:18 tgl Exp $
  *
  * NOTES
  *   Path and Plan nodes do not have any readfuncs support, because we
@@ -708,6 +708,23 @@ _readMinMaxExpr(void)
    READ_DONE();
 }
 
+/*
+ * _readXmlExpr
+ */
+static XmlExpr *
+_readXmlExpr(void)
+{
+   READ_LOCALS(XmlExpr);
+
+   READ_ENUM_FIELD(op, XmlExprOp);
+   READ_STRING_FIELD(name);
+   READ_NODE_FIELD(named_args);
+   READ_NODE_FIELD(arg_names);
+   READ_NODE_FIELD(args);
+
+   READ_DONE();
+}
+
 /*
  * _readNullIfExpr
  */
@@ -764,22 +781,6 @@ _readBooleanTest(void)
    READ_DONE();
 }
 
-/*
- * _readXmlExpr
- */
-static XmlExpr *
-_readXmlExpr(void)
-{
-   READ_LOCALS(XmlExpr);
-
-   READ_ENUM_FIELD(op, XmlExprOp);
-   READ_STRING_FIELD(name);
-   READ_NODE_FIELD(named_args);
-   READ_NODE_FIELD(args);
-
-   READ_DONE();
-}
-
 /*
  * _readCoerceToDomain
  */
@@ -1024,14 +1025,14 @@ parseNodeString(void)
        return_value = _readCoalesceExpr();
    else if (MATCH("MINMAX", 6))
        return_value = _readMinMaxExpr();
+   else if (MATCH("XMLEXPR", 7))
+       return_value = _readXmlExpr();
    else if (MATCH("NULLIFEXPR", 10))
        return_value = _readNullIfExpr();
    else if (MATCH("NULLTEST", 8))
        return_value = _readNullTest();
    else if (MATCH("BOOLEANTEST", 11))
        return_value = _readBooleanTest();
-   else if (MATCH("XMLEXPR", 7))
-       return_value = _readXmlExpr();
    else if (MATCH("COERCETODOMAIN", 14))
        return_value = _readCoerceToDomain();
    else if (MATCH("COERCETODOMAINVALUE", 19))
index 0f720c40e932e8a5563d1cdab4cd1188f62545ba..5ad97aabc3439d997d5246face2ccd16643d7b79 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.225 2006/12/23 00:43:10 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.226 2006/12/24 00:29:18 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -557,10 +557,10 @@ expression_returns_set_walker(Node *node, void *context)
        return false;
    if (IsA(node, MinMaxExpr))
        return false;
-   if (IsA(node, NullIfExpr))
-       return false;
    if (IsA(node, XmlExpr))
        return false;
+   if (IsA(node, NullIfExpr))
+       return false;
 
    return expression_tree_walker(node, expression_returns_set_walker,
                                  context);
@@ -872,14 +872,14 @@ contain_nonstrict_functions_walker(Node *node, void *context)
        return true;
    if (IsA(node, MinMaxExpr))
        return true;
+   if (IsA(node, XmlExpr))
+       return true;
    if (IsA(node, NullIfExpr))
        return true;
    if (IsA(node, NullTest))
        return true;
    if (IsA(node, BooleanTest))
        return true;
-   if (IsA(node, XmlExpr))
-       return true;
    return expression_tree_walker(node, contain_nonstrict_functions_walker,
                                  context);
 }
@@ -3328,22 +3328,23 @@ expression_tree_walker(Node *node,
            return walker(((CoalesceExpr *) node)->args, context);
        case T_MinMaxExpr:
            return walker(((MinMaxExpr *) node)->args, context);
-       case T_NullIfExpr:
-           return walker(((NullIfExpr *) node)->args, context);
-       case T_NullTest:
-           return walker(((NullTest *) node)->arg, context);
-       case T_BooleanTest:
-           return walker(((BooleanTest *) node)->arg, context);
        case T_XmlExpr:
            {
                XmlExpr *xexpr = (XmlExpr *) node;
                
                if (walker(xexpr->named_args, context))
                    return true;
+               /* we assume walker doesn't care about arg_names */
                if (walker(xexpr->args, context))
                    return true;
            }
            break;
+       case T_NullIfExpr:
+           return walker(((NullIfExpr *) node)->args, context);
+       case T_NullTest:
+           return walker(((NullTest *) node)->arg, context);
+       case T_BooleanTest:
+           return walker(((BooleanTest *) node)->arg, context);
        case T_CoerceToDomain:
            return walker(((CoerceToDomain *) node)->arg, context);
        case T_TargetEntry:
@@ -3874,6 +3875,7 @@ expression_tree_mutator(Node *node,
 
                FLATCOPY(newnode, xexpr, XmlExpr);
                MUTATE(newnode->named_args, xexpr->named_args, List *);
+               /* assume mutator does not care about arg_names */
                MUTATE(newnode->args, xexpr->args, List *);
                return (Node *) newnode;
            }
index cc400407363e660df5060a223cf8c1b27a8cf152..a1511870f28a425bd6f37e69b33313d9bca2a9c8 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.569 2006/12/21 16:05:14 petere Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.570 2006/12/24 00:29:18 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -348,8 +348,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
 
 %type <target> xml_attribute_el
 %type <list>   xml_attribute_list xml_attributes
-%type <node>   xml_root_version
-%type <ival>   opt_xml_root_standalone document_or_content xml_whitespace_option
+%type <node>   xml_root_version opt_xml_root_standalone
+%type <boolean>    document_or_content xml_whitespace_option
 
 
 /*
@@ -371,13 +371,13 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
    CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
    CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
    COMMITTED CONCURRENTLY CONNECTION CONSTRAINT CONSTRAINTS
-   CONTENT CONVERSION_P CONVERT COPY CREATE CREATEDB
+   CONTENT_P CONVERSION_P CONVERT COPY CREATE CREATEDB
    CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME
    CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
 
    DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
    DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS
-   DESC DISABLE_P DISTINCT DO DOCUMENT DOMAIN_P DOUBLE_P DROP
+   DESC DISABLE_P DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP
 
    EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING
    EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
@@ -404,7 +404,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
 
    MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
 
-   NAME NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
+   NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
    NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
    NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC
 
@@ -423,9 +423,9 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
 
    SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
    SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
-   SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE START STATEMENT
-   STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP SUBSTRING SUPERUSER_P SYMMETRIC
-   SYSID SYSTEM_P
+   SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE_P START STATEMENT
+   STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING SUPERUSER_P
+   SYMMETRIC SYSID SYSTEM_P
 
    TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
    TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
@@ -434,15 +434,15 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
    UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL
    UPDATE USER USING
 
-   VACUUM VALID VALIDATOR VALUE VALUES VARCHAR VARYING
-   VERBOSE VERSION VIEW VOLATILE
+   VACUUM VALID VALIDATOR VALUE_P VALUES VARCHAR VARYING
+   VERBOSE VERSION_P VIEW VOLATILE
 
-   WHEN WHERE WHITESPACE WITH WITHOUT WORK WRITE
+   WHEN WHERE WHITESPACE_P WITH WITHOUT WORK WRITE
 
    XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
    XMLPI XMLROOT XMLSERIALIZE
 
-   YEAR_P YES
+   YEAR_P YES_P
 
    ZONE
 
@@ -493,7 +493,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
  * left-associativity among the JOIN rules themselves.
  */
 %left      JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
-%right     PRESERVE STRIP
+/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */
+%right     PRESERVE STRIP_P
 %%
 
 /*
@@ -7880,95 +7881,54 @@ func_expr:  func_name '(' ')'
                }
            | XMLCONCAT '(' expr_list ')'
                {       
-                   $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NULL, $3);
+                   $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NIL, $3);
                }
-           | XMLELEMENT '(' NAME ColLabel ')'
+           | XMLELEMENT '(' NAME_P ColLabel ')'
                {
-                   $$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, NULL);
+                   $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, NIL);
                }
-           | XMLELEMENT '(' NAME ColLabel ',' xml_attributes ')'
+           | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ')'
                {
-                   $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NULL);
+                   $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NIL);
                }
-           | XMLELEMENT '(' NAME ColLabel ',' expr_list ')'
+           | XMLELEMENT '(' NAME_P ColLabel ',' expr_list ')'
                {
-                   $$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, $6);
+                   $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, $6);
                }
-           | XMLELEMENT '(' NAME ColLabel ',' xml_attributes ',' expr_list ')'
+           | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ',' expr_list ')'
                {
                    $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8);
                }
            | XMLFOREST '(' xml_attribute_list ')'
                {
-                   $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NULL);
+                   $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NIL);
                }
            | XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'
                {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = SystemFuncName("xmlparse");
-                   n->args = list_make3(makeBoolAConst($3 == DOCUMENT), $4, makeBoolAConst($5 == PRESERVE));
-                   n->agg_star = FALSE;
-                   n->agg_distinct = FALSE;
-                   n->location = @1;
-                   $$ = (Node *)n;
+                   $$ = makeXmlExpr(IS_XMLPARSE, NULL, NIL,
+                                    list_make3($4,
+                                               makeBoolAConst($3),
+                                               makeBoolAConst($5)));
                }
-           | XMLPI '(' NAME ColLabel ')'
+           | XMLPI '(' NAME_P ColLabel ')'
                {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = SystemFuncName("xmlpi");
-                   n->args = list_make1(makeStringConst($4, NULL));
-                   n->agg_star = FALSE;
-                   n->agg_distinct = FALSE;
-                   n->location = @1;
-                   $$ = (Node *)n;
+                   $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NIL);
                }
-           | XMLPI '(' NAME ColLabel ',' a_expr ')'
+           | XMLPI '(' NAME_P ColLabel ',' a_expr ')'
                {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = SystemFuncName("xmlpi");
-                   n->args = list_make2(makeStringConst($4, NULL), $6);
-                   n->agg_star = FALSE;
-                   n->agg_distinct = FALSE;
-                   n->location = @1;
-                   $$ = (Node *)n;
+                   $$ = makeXmlExpr(IS_XMLPI, $4, NULL, list_make1($6));
                }
            | XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')'
                {
-                   FuncCall *n = makeNode(FuncCall);
-                   Node *ver;
-                   A_Const *sa;
-
-                   if ($5)
-                       ver = $5;
-                   else
-                   {
-                       A_Const *val;
-
-                       val = makeNode(A_Const);
-                       val->val.type = T_Null;
-                       ver = (Node *) val;
-                   }
-
-                   if ($6)
-                       sa = makeBoolAConst($6 == 1);
-                   else
-                   {
-                       sa = makeNode(A_Const);
-                       sa->val.type = T_Null;
-                   }
-
-                   n->funcname = SystemFuncName("xmlroot");
-                   n->args = list_make3($3, ver, sa);
-                   n->agg_star = FALSE;
-                   n->agg_distinct = FALSE;
-                   n->location = @1;
-                   $$ = (Node *)n;
+                   $$ = makeXmlExpr(IS_XMLROOT, NULL, NIL,
+                                    list_make3($3, $5, $6));
                }
            | XMLSERIALIZE '(' document_or_content a_expr AS Typename ')'
                {
                    /*
                     * FIXME: This should be made distinguishable from
-                    * CAST (for reverse compilation at least).
+                    * CAST (for reverse compilation at least).  Also,
+                    * what about the document/content option??
                     */
                    $$ = makeTypeCast($4, $6);
                }
@@ -7977,17 +7937,35 @@ func_expr:  func_name '(' ')'
 /*
  * SQL/XML support
  */
-xml_root_version: VERSION a_expr   { $$ = $2; }
-           | VERSION NO VALUE      { $$ = NULL; }
+xml_root_version: VERSION_P a_expr
+               { $$ = $2; }
+           | VERSION_P NO VALUE_P
+               {
+                   A_Const *val = makeNode(A_Const);
+                   val->val.type = T_Null;
+                   $$ = (Node *) val;
+               }
        ;
 
-opt_xml_root_standalone: ',' STANDALONE YES    { $$ = 1; }
-           | ',' STANDALONE NO             { $$ = -1; }
-           | ',' STANDALONE NO VALUE       { $$ = 0; }
-           | /*EMPTY*/                     { $$ = 0; }
+opt_xml_root_standalone: ',' STANDALONE_P YES_P
+               { $$ = (Node *) makeBoolAConst(true); }
+           | ',' STANDALONE_P NO
+               { $$ = (Node *) makeBoolAConst(false); }
+           | ',' STANDALONE_P NO VALUE_P
+               {
+                   A_Const *val = makeNode(A_Const);
+                   val->val.type = T_Null;
+                   $$ = (Node *) val;
+               }
+           | /*EMPTY*/
+               {
+                   A_Const *val = makeNode(A_Const);
+                   val->val.type = T_Null;
+                   $$ = (Node *) val;
+               }
        ;
 
-xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; }
+xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')'   { $$ = $3; }
        ;
 
 xml_attribute_list:    xml_attribute_el                    { $$ = list_make1($1); }
@@ -8000,7 +7978,7 @@ xml_attribute_el: a_expr AS ColLabel
                    $$->name = $3;
                    $$->indirection = NULL;
                    $$->val = (Node *) $1;
-
+                   $$->location = @1;
                }
            | a_expr
                {
@@ -8008,16 +7986,21 @@ xml_attribute_el: a_expr AS ColLabel
                    $$->name = NULL;
                    $$->indirection = NULL;
                    $$->val = (Node *) $1;              
+                   $$->location = @1;
                }
        ;
 
-document_or_content: DOCUMENT { $$ = DOCUMENT; }
-           | CONTENT { $$ = CONTENT; }
+document_or_content: DOCUMENT_P                        { $$ = TRUE; }
+           | CONTENT_P                             { $$ = FALSE; }
        ;
 
-xml_whitespace_option: PRESERVE WHITESPACE { $$ = PRESERVE; }
-           | STRIP WHITESPACE { $$ = STRIP; }
-           | /*EMPTY*/ { $$ = STRIP; }
+/*
+ * XXX per SQL spec, the default should be STRIP WHITESPACE, but since we
+ * haven't implemented that yet, temporarily default to PRESERVE.
+ */
+xml_whitespace_option: PRESERVE WHITESPACE_P       { $$ = TRUE; }
+           | STRIP_P WHITESPACE_P                  { $$ = FALSE; }
+           | /*EMPTY*/                             { $$ = TRUE; }
        ;
 
 /*
@@ -8712,7 +8695,7 @@ unreserved_keyword:
            | CONCURRENTLY
            | CONNECTION
            | CONSTRAINTS
-           | CONTENT
+           | CONTENT_P
            | CONVERSION_P
            | COPY
            | CREATEDB
@@ -8732,7 +8715,7 @@ unreserved_keyword:
            | DELIMITER
            | DELIMITERS
            | DISABLE_P
-           | DOCUMENT
+           | DOCUMENT_P
            | DOMAIN_P
            | DOUBLE_P
            | DROP
@@ -8792,7 +8775,7 @@ unreserved_keyword:
            | MODE
            | MONTH_P
            | MOVE
-           | NAME
+           | NAME_P
            | NAMES
            | NEXT
            | NO
@@ -8853,18 +8836,18 @@ unreserved_keyword:
            | SHOW
            | SIMPLE
            | STABLE
-           | STANDALONE
+           | STANDALONE_P
            | START
            | STATEMENT
            | STATISTICS
            | STDIN
            | STDOUT
            | STORAGE
-           | STRIP
+           | STRICT_P
+           | STRIP_P
            | SUPERUSER_P
            | SYSID
            | SYSTEM_P
-           | STRICT_P
            | TABLESPACE
            | TEMP
            | TEMPLATE
@@ -8883,18 +8866,18 @@ unreserved_keyword:
            | VACUUM
            | VALID
            | VALIDATOR
+           | VALUE_P
            | VARYING
-           | VERSION
+           | VERSION_P
            | VIEW
-           | VALUE
            | VOLATILE
-           | WHITESPACE
+           | WHITESPACE_P
            | WITH
            | WITHOUT
            | WORK
            | WRITE
            | YEAR_P
-           | YES
+           | YES_P
            | ZONE
        ;
 
@@ -8948,8 +8931,8 @@ col_name_keyword:
            | VALUES
            | VARCHAR
            | XMLATTRIBUTES
-           | XMLELEMENT
            | XMLCONCAT
+           | XMLELEMENT
            | XMLFOREST
            | XMLPARSE
            | XMLPI
@@ -9492,10 +9475,16 @@ doNegateFloat(Value *v)
 static Node *
 makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
 {
-   XmlExpr *x = makeNode(XmlExpr);
+   XmlExpr    *x = makeNode(XmlExpr);
+
    x->op = op;
    x->name = name;
+   /*
+    * named_args is a list of ResTarget; it'll be split apart into separate
+    * expression and name lists in transformXmlExpr().
+    */
    x->named_args = named_args;
+   x->arg_names = NIL;
    x->args = args;
    return (Node *) x;
 }
index b5e49e955fc1e30173731bff1f457b0a30e8e6e7..4865d360b3efd2e51d77f9a780f4bceaacb65300 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.178 2006/12/21 16:05:14 petere Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.179 2006/12/24 00:29:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -89,7 +89,7 @@ static const ScanKeyword ScanKeywords[] = {
    {"connection", CONNECTION},
    {"constraint", CONSTRAINT},
    {"constraints", CONSTRAINTS},
-   {"content", CONTENT},
+   {"content", CONTENT_P},
    {"conversion", CONVERSION_P},
    {"convert", CONVERT},
    {"copy", COPY},
@@ -124,7 +124,7 @@ static const ScanKeyword ScanKeywords[] = {
    {"disable", DISABLE_P},
    {"distinct", DISTINCT},
    {"do", DO},
-   {"document", DOCUMENT},
+   {"document", DOCUMENT_P},
    {"domain", DOMAIN_P},
    {"double", DOUBLE_P},
    {"drop", DROP},
@@ -220,7 +220,7 @@ static const ScanKeyword ScanKeywords[] = {
    {"mode", MODE},
    {"month", MONTH_P},
    {"move", MOVE},
-   {"name", NAME},
+   {"name", NAME_P},
    {"names", NAMES},
    {"national", NATIONAL},
    {"natural", NATURAL},
@@ -317,7 +317,7 @@ static const ScanKeyword ScanKeywords[] = {
    {"smallint", SMALLINT},
    {"some", SOME},
    {"stable", STABLE},
-   {"standalone", STANDALONE},
+   {"standalone", STANDALONE_P},
    {"start", START},
    {"statement", STATEMENT},
    {"statistics", STATISTICS},
@@ -325,7 +325,7 @@ static const ScanKeyword ScanKeywords[] = {
    {"stdout", STDOUT},
    {"storage", STORAGE},
    {"strict", STRICT_P},
-   {"strip", STRIP},
+   {"strip", STRIP_P},
    {"substring", SUBSTRING},
    {"superuser", SUPERUSER_P},
    {"symmetric", SYMMETRIC},
@@ -362,17 +362,17 @@ static const ScanKeyword ScanKeywords[] = {
    {"vacuum", VACUUM},
    {"valid", VALID},
    {"validator", VALIDATOR},
-   {"value", VALUE},
+   {"value", VALUE_P},
    {"values", VALUES},
    {"varchar", VARCHAR},
    {"varying", VARYING},
    {"verbose", VERBOSE},
-   {"version", VERSION},
+   {"version", VERSION_P},
    {"view", VIEW},
    {"volatile", VOLATILE},
    {"when", WHEN},
    {"where", WHERE},
-   {"whitespace", WHITESPACE},
+   {"whitespace", WHITESPACE_P},
    {"with", WITH},
    {"without", WITHOUT},
    {"work", WORK},
@@ -386,7 +386,7 @@ static const ScanKeyword ScanKeywords[] = {
    {"xmlroot", XMLROOT},
    {"xmlserialize", XMLSERIALIZE},
    {"year", YEAR_P},
-   {"yes", YES},
+   {"yes", YES_P},
    {"zone", ZONE},
 };
 
index 996c724d1cec46c1709e0d239d81c26336446037..145caab101a47822c76dfbd1ad28b1812d28ccf8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.159 2006/11/28 12:54:41 petere Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.160 2006/12/24 00:29:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1094,7 +1094,7 @@ transformLimitClause(ParseState *pstate, Node *clause,
 
    qual = transformExpr(pstate, clause);
 
-   qual = coerce_to_bigint(pstate, qual, constructName);
+   qual = coerce_to_specific_type(pstate, qual, INT8OID, constructName);
 
    /*
     * LIMIT can't refer to any vars or aggregates of the current query; we
index 5670ed4fe742188c1b00a03f57340b95a4881edd..45c8e97be1d24f5ab95a2c402c8b8176af83f362 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.148 2006/12/21 16:05:14 petere Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.149 2006/12/24 00:29:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -840,8 +840,8 @@ coerce_to_boolean(ParseState *pstate, Node *node,
 }
 
 /*
- * coerce_to_integer()
- *     Coerce an argument of a construct that requires integer input.
+ * coerce_to_specific_type()
+ *     Coerce an argument of a construct that requires a specific data type.
  *     Also check that input is not a set.
  *
  * Returns the possibly-transformed node tree.
@@ -850,103 +850,26 @@ coerce_to_boolean(ParseState *pstate, Node *node,
  * processing is wanted.
  */
 Node *
-coerce_to_integer(ParseState *pstate, Node *node,
-                 const char *constructName)
-{
-   Oid         inputTypeId = exprType(node);
-
-   if (inputTypeId != INT4OID)
-   {
-       node = coerce_to_target_type(pstate, node, inputTypeId,
-                                    INT4OID, -1,
-                                    COERCION_ASSIGNMENT,
-                                    COERCE_IMPLICIT_CAST);
-       if (node == NULL)
-           ereport(ERROR,
-                   (errcode(ERRCODE_DATATYPE_MISMATCH),
-           /* translator: first %s is name of a SQL construct, eg LIMIT */
-                  errmsg("argument of %s must be type integer, not type %s",
-                         constructName, format_type_be(inputTypeId))));
-   }
-
-   if (expression_returns_set(node))
-       ereport(ERROR,
-               (errcode(ERRCODE_DATATYPE_MISMATCH),
-       /* translator: %s is name of a SQL construct, eg LIMIT */
-                errmsg("argument of %s must not return a set",
-                       constructName)));
-
-   return node;
-}
-
-/*
- * coerce_to_bigint()
- *     Coerce an argument of a construct that requires int8 input.
- *     Also check that input is not a set.
- *
- * Returns the possibly-transformed node tree.
- *
- * As with coerce_type, pstate may be NULL if no special unknown-Param
- * processing is wanted.
- */
-Node *
-coerce_to_bigint(ParseState *pstate, Node *node,
-                const char *constructName)
-{
-   Oid         inputTypeId = exprType(node);
-
-   if (inputTypeId != INT8OID)
-   {
-       node = coerce_to_target_type(pstate, node, inputTypeId,
-                                    INT8OID, -1,
-                                    COERCION_ASSIGNMENT,
-                                    COERCE_IMPLICIT_CAST);
-       if (node == NULL)
-           ereport(ERROR,
-                   (errcode(ERRCODE_DATATYPE_MISMATCH),
-           /* translator: first %s is name of a SQL construct, eg LIMIT */
-                    errmsg("argument of %s must be type bigint, not type %s",
-                           constructName, format_type_be(inputTypeId))));
-   }
-
-   if (expression_returns_set(node))
-       ereport(ERROR,
-               (errcode(ERRCODE_DATATYPE_MISMATCH),
-       /* translator: %s is name of a SQL construct, eg LIMIT */
-                errmsg("argument of %s must not return a set",
-                       constructName)));
-
-   return node;
-}
-
-/*
- * coerce_to_xml()
- *     Coerce an argument of a construct that requires xml input.
- *     Also check that input is not a set.
- *
- * Returns the possibly-transformed node tree.
- *
- * As with coerce_type, pstate may be NULL if no special unknown-Param
- * processing is wanted.
- */
-Node *
-coerce_to_xml(ParseState *pstate, Node *node,
-                const char *constructName)
+coerce_to_specific_type(ParseState *pstate, Node *node,
+                       Oid targetTypeId,
+                       const char *constructName)
 {
    Oid         inputTypeId = exprType(node);
 
-   if (inputTypeId != XMLOID)
+   if (inputTypeId != targetTypeId)
    {
        node = coerce_to_target_type(pstate, node, inputTypeId,
-                                    XMLOID, -1,
+                                    targetTypeId, -1,
                                     COERCION_ASSIGNMENT,
                                     COERCE_IMPLICIT_CAST);
        if (node == NULL)
            ereport(ERROR,
                    (errcode(ERRCODE_DATATYPE_MISMATCH),
            /* translator: first %s is name of a SQL construct, eg LIMIT */
-                    errmsg("argument of %s must be type xml, not type %s",
-                           constructName, format_type_be(inputTypeId))));
+                  errmsg("argument of %s must be type %s, not type %s",
+                         constructName,
+                         format_type_be(targetTypeId),
+                         format_type_be(inputTypeId))));
    }
 
    if (expression_returns_set(node))
index 2a48741b3a2fef31be935b3beacca84411c3c1f3..7dbbb9a33a8637b97338756d22cd8cf027dc2416 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.201 2006/12/23 00:43:11 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.202 2006/12/24 00:29:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -220,6 +220,10 @@ transformExpr(ParseState *pstate, Node *expr)
            result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
            break;
 
+       case T_XmlExpr:
+           result = transformXmlExpr(pstate, (XmlExpr *) expr);
+           break;
+
        case T_NullTest:
            {
                NullTest   *n = (NullTest *) expr;
@@ -234,10 +238,6 @@ transformExpr(ParseState *pstate, Node *expr)
            result = transformBooleanTest(pstate, (BooleanTest *) expr);
            break;
 
-       case T_XmlExpr:
-           result = transformXmlExpr(pstate, (XmlExpr *) expr);
-           break;
-
            /*********************************************
             * Quietly accept node types that may be presented when we are
             * called on an already-transformed tree.
@@ -1375,6 +1375,107 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
    return (Node *) newm;
 }
 
+static Node *
+transformXmlExpr(ParseState *pstate, XmlExpr *x)
+{
+   XmlExpr *newx = makeNode(XmlExpr);
+   ListCell    *lc;
+   int         i;
+
+   newx->op = x->op;
+   if (x->name)
+       newx->name = map_sql_identifier_to_xml_name(x->name, false);
+   else
+       newx->name = NULL;
+
+   /*
+    * gram.y built the named args as a list of ResTarget.  Transform each,
+    * and break the names out as a separate list.
+    */
+   newx->named_args = NIL;
+   newx->arg_names = NIL;
+
+   foreach(lc, x->named_args)
+   {
+       ResTarget   *r = (ResTarget *) lfirst(lc);
+       Node        *expr;
+       char        *argname;
+
+       Assert(IsA(r, ResTarget));
+
+       expr = transformExpr(pstate, r->val);
+
+       if (r->name)
+           argname = map_sql_identifier_to_xml_name(r->name, false);
+       else if (IsA(r->val, ColumnRef))
+           argname = map_sql_identifier_to_xml_name(FigureColname(r->val),
+                                                    true);
+       else
+       {
+           ereport(ERROR,
+                   (errcode(ERRCODE_SYNTAX_ERROR),
+                    x->op == IS_XMLELEMENT
+                    ? errmsg("unnamed attribute value must be a column reference")
+                    : errmsg("unnamed element value must be a column reference")));
+           argname = NULL;     /* keep compiler quiet */
+       }
+
+       newx->named_args = lappend(newx->named_args, expr);
+       newx->arg_names = lappend(newx->arg_names, makeString(argname));
+   }
+
+   /* The other arguments are of varying types depending on the function */
+   newx->args = NIL;
+   i = 0;
+   foreach(lc, x->args)
+   {
+       Node       *e = (Node *) lfirst(lc);
+       Node       *newe;
+
+       newe = transformExpr(pstate, e);
+       switch (x->op)
+       {
+           case IS_XMLCONCAT:
+               newe = coerce_to_specific_type(pstate, newe, XMLOID,
+                                              "XMLCONCAT");
+               break;
+           case IS_XMLELEMENT:
+               newe = coerce_to_specific_type(pstate, newe, XMLOID,
+                                              "XMLELEMENT");
+               break;
+           case IS_XMLFOREST:
+               newe = coerce_to_specific_type(pstate, newe, XMLOID,
+                                              "XMLFOREST");
+               break;
+           case IS_XMLPARSE:
+               if (i == 0)
+                   newe = coerce_to_specific_type(pstate, newe, TEXTOID,
+                                                  "XMLPARSE");
+               else
+                   newe = coerce_to_boolean(pstate, newe, "XMLPARSE");
+               break;
+           case IS_XMLPI:
+               newe = coerce_to_specific_type(pstate, newe, TEXTOID,
+                                              "XMLPI");
+               break;
+           case IS_XMLROOT:
+               if (i == 0)
+                   newe = coerce_to_specific_type(pstate, newe, XMLOID,
+                                                  "XMLROOT");
+               else if (i == 1)
+                   newe = coerce_to_specific_type(pstate, newe, TEXTOID,
+                                                  "XMLROOT");
+               else
+                   newe = coerce_to_boolean(pstate, newe, "XMLROOT");
+               break;
+       }
+       newx->args = lappend(newx->args, newe);
+       i++;
+   }
+       
+   return (Node *) newx;
+}
+
 static Node *
 transformBooleanTest(ParseState *pstate, BooleanTest *b)
 {
@@ -1415,56 +1516,6 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
    return (Node *) b;
 }
 
-static Node *
-transformXmlExpr(ParseState *pstate, XmlExpr *x)
-{
-   ListCell    *lc;
-   XmlExpr *newx = makeNode(XmlExpr);
-
-   newx->op = x->op;
-   if (x->name)
-       newx->name = map_sql_identifier_to_xml_name(x->name, false);
-   else
-       newx->name = NULL;
-
-   foreach(lc, x->named_args)
-   {
-       ResTarget   *r = (ResTarget *) lfirst(lc);
-       Node        *expr = transformExpr(pstate, r->val);
-       char        *argname = NULL;
-
-       if (r->name)
-           argname = map_sql_identifier_to_xml_name(r->name, false);
-       else if (IsA(r->val, ColumnRef))
-           argname = map_sql_identifier_to_xml_name(FigureColname(r->val), true);
-       else
-           ereport(ERROR,
-                   (errcode(ERRCODE_SYNTAX_ERROR),
-                    x->op == IS_XMLELEMENT
-                    ? errmsg("unnamed attribute value must be a column reference")
-                    : errmsg("unnamed element value must be a column reference")));
-
-       newx->named_args = lappend(newx->named_args, 
-                                  makeTargetEntry((Expr *) expr, 0, argname, false)); 
-   }
-
-   foreach(lc, x->args)
-   {
-       Node       *e = (Node *) lfirst(lc);
-       Node       *newe;
-
-       newe = coerce_to_xml(pstate, transformExpr(pstate, e),
-                            (x->op == IS_XMLCONCAT 
-                             ? "XMLCONCAT"
-                             : (x->op == IS_XMLELEMENT
-                                ? "XMLELEMENT"
-                                : "XMLFOREST")));
-       newx->args = lappend(newx->args, newe);
-   }
-       
-   return (Node *) newx;
-}
-
 /*
  * Construct a whole-row reference to represent the notation "relation.*".
  *
@@ -1715,6 +1766,9 @@ exprType(Node *expr)
        case T_MinMaxExpr:
            type = ((MinMaxExpr *) expr)->minmaxtype;
            break;
+       case T_XmlExpr:
+           type = XMLOID;
+           break;
        case T_NullIfExpr:
            type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
            break;
@@ -1724,9 +1778,6 @@ exprType(Node *expr)
        case T_BooleanTest:
            type = BOOLOID;
            break;
-       case T_XmlExpr:
-           type = XMLOID;
-           break;
        case T_CoerceToDomain:
            type = ((CoerceToDomain *) expr)->resulttype;
            break;
index 906d96e45c6c6f069476dae44952c5236819a0b5..ef4b9083ac652c702aef78cf4e9e727c94ad0d02 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.150 2006/12/21 16:05:14 petere Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.151 2006/12/24 00:29:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1328,6 +1328,15 @@ FigureColnameInternal(Node *node, char **name)
                case IS_XMLFOREST:
                    *name = "xmlforest";
                    return 2;
+               case IS_XMLPARSE:
+                   *name = "xmlparse";
+                   return 2;
+               case IS_XMLPI:
+                   *name = "xmlpi";
+                   return 2;
+               case IS_XMLROOT:
+                   *name = "xmlroot";
+                   return 2;
            } 
            break;
        default:
index b2ff95f457b758576b38504e6a1355384b87ec95..699b4a9370462431f72d0b6223fae151cf3da660 100644 (file)
@@ -2,7 +2,7 @@
  * ruleutils.c - Functions to convert stored expressions/querytrees
  *             back to source text
  *
- *   $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.237 2006/12/23 00:43:11 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.238 2006/12/24 00:29:19 tgl Exp $
  **********************************************************************/
 
 #include "postgres.h"
@@ -2988,8 +2988,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
        case T_RowExpr:
        case T_CoalesceExpr:
        case T_MinMaxExpr:
-       case T_NullIfExpr:
        case T_XmlExpr:
+       case T_NullIfExpr:
        case T_Aggref:
        case T_FuncExpr:
            /* function-like: name(..) or name[..] */
@@ -3097,8 +3097,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
                case T_RowExpr: /* other separators */
                case T_CoalesceExpr:    /* own parentheses */
                case T_MinMaxExpr:      /* own parentheses */
-               case T_NullIfExpr:      /* other separators */
                case T_XmlExpr:         /* own parentheses */
+               case T_NullIfExpr:      /* other separators */
                case T_Aggref:  /* own parentheses */
                case T_CaseExpr:        /* other separators */
                    return true;
@@ -3146,8 +3146,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
                case T_RowExpr: /* other separators */
                case T_CoalesceExpr:    /* own parentheses */
                case T_MinMaxExpr:      /* own parentheses */
-               case T_NullIfExpr:      /* other separators */
                case T_XmlExpr:         /* own parentheses */
+               case T_NullIfExpr:      /* other separators */
                case T_Aggref:  /* own parentheses */
                case T_CaseExpr:        /* other separators */
                    return true;
@@ -3779,6 +3779,140 @@ get_rule_expr(Node *node, deparse_context *context,
            }
            break;
 
+       case T_XmlExpr:
+           {
+               XmlExpr *xexpr = (XmlExpr *) node;
+               bool    needcomma = false;
+               ListCell   *arg;
+               ListCell   *narg;
+               Const      *con;
+
+               switch (xexpr->op)
+               {
+                   case IS_XMLCONCAT:
+                       appendStringInfoString(buf, "XMLCONCAT(");
+                       break;
+                   case IS_XMLELEMENT:
+                       appendStringInfoString(buf, "XMLELEMENT(");
+                       break;
+                   case IS_XMLFOREST:
+                       appendStringInfoString(buf, "XMLFOREST(");
+                       break;
+                   case IS_XMLPARSE:
+                       appendStringInfoString(buf, "XMLPARSE(");
+                       break;
+                   case IS_XMLPI:
+                       appendStringInfoString(buf, "XMLPI(");
+                       break;
+                   case IS_XMLROOT:
+                       appendStringInfoString(buf, "XMLROOT(");
+                       break;
+               }
+               if (xexpr->name)
+               {
+                   /*
+                    * XXX need to de-escape the name
+                    */
+                   appendStringInfo(buf, "NAME %s",
+                                    quote_identifier(xexpr->name));
+                   needcomma = true;
+               }
+               if (xexpr->named_args)
+               {
+                   if (xexpr->op != IS_XMLFOREST)
+                   {
+                       if (needcomma)
+                           appendStringInfoString(buf, ", ");
+                       appendStringInfoString(buf, "XMLATTRIBUTES(");
+                       needcomma = false;
+                   }
+                   forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
+                   {
+                       Node    *e = (Node *) lfirst(arg);
+                       char    *argname = strVal(lfirst(narg));
+
+                       if (needcomma)
+                           appendStringInfoString(buf, ", ");
+                       get_rule_expr((Node *) e, context, true);
+                       /*
+                        * XXX need to de-escape the name
+                        */
+                       appendStringInfo(buf, " AS %s",
+                                        quote_identifier(argname));
+                       needcomma = true;
+                   }
+                   if (xexpr->op != IS_XMLFOREST)
+                       appendStringInfoChar(buf, ')');
+               }
+               if (xexpr->args)
+               {
+                   if (needcomma)
+                       appendStringInfoString(buf, ", ");
+                   switch (xexpr->op)
+                   {
+                       case IS_XMLCONCAT:
+                       case IS_XMLELEMENT:
+                       case IS_XMLFOREST:
+                       case IS_XMLPI:
+                           /* no extra decoration needed */
+                           get_rule_expr((Node *) xexpr->args, context, true);
+                           break;
+                       case IS_XMLPARSE:
+                           Assert(list_length(xexpr->args) == 3);
+
+                           con = (Const *) lsecond(xexpr->args);
+                           Assert(IsA(con, Const));
+                           Assert(!con->constisnull);
+                           if (DatumGetBool(con->constvalue))
+                               appendStringInfoString(buf, "DOCUMENT ");
+                           else
+                               appendStringInfoString(buf, "CONTENT ");
+
+                           get_rule_expr((Node *) linitial(xexpr->args),
+                                         context, true);
+
+                           con = (Const *) lthird(xexpr->args);
+                           Assert(IsA(con, Const));
+                           Assert(!con->constisnull);
+                           if (DatumGetBool(con->constvalue))
+                               appendStringInfoString(buf,
+                                                      " PRESERVE WHITESPACE");
+                           else
+                               appendStringInfoString(buf,
+                                                      " STRIP WHITESPACE");
+                           break;
+                       case IS_XMLROOT:
+                           Assert(list_length(xexpr->args) == 3);
+
+                           get_rule_expr((Node *) linitial(xexpr->args),
+                                         context, true);
+
+                           appendStringInfoString(buf, ", VERSION ");
+                           con = (Const *) lsecond(xexpr->args);
+                           if (IsA(con, Const) &&
+                               con->constisnull)
+                               appendStringInfoString(buf, "NO VALUE");
+                           else
+                               get_rule_expr((Node *) con, context, false);
+
+                           con = (Const *) lthird(xexpr->args);
+                           Assert(IsA(con, Const));
+                           if (con->constisnull)
+                               /* suppress STANDALONE NO VALUE */ ;
+                           else if (DatumGetBool(con->constvalue))
+                               appendStringInfoString(buf,
+                                                      ", STANDALONE YES");
+                           else
+                               appendStringInfoString(buf,
+                                                      ", STANDALONE NO");
+                           break;
+                   }
+
+               }
+               appendStringInfoChar(buf, ')');
+           }
+           break;
+
        case T_NullIfExpr:
            {
                NullIfExpr *nullifexpr = (NullIfExpr *) node;
@@ -3849,28 +3983,6 @@ get_rule_expr(Node *node, deparse_context *context,
            }
            break;
 
-       case T_XmlExpr:
-           {
-               XmlExpr *xexpr = (XmlExpr *) node;
-
-               switch (xexpr->op)
-               {
-                   case IS_XMLCONCAT:
-                       appendStringInfo(buf, "XMLCONCAT(");
-                       break;
-                   case IS_XMLELEMENT:
-                       appendStringInfo(buf, "XMLELEMENT(");
-                       break;
-                   case IS_XMLFOREST:
-                       appendStringInfo(buf, "XMLFOREST(");
-                       break;
-               }
-               get_rule_expr((Node *) xexpr->named_args, context, true);
-               get_rule_expr((Node *) xexpr->args, context, true);
-               appendStringInfoChar(buf, ')');
-           }
-           break;
-
        case T_CoerceToDomain:
            {
                CoerceToDomain *ctest = (CoerceToDomain *) node;
index d765c8657fb5a5110ca464b1a4af8e5d5b9be805..a6dc1a6e5f02a876e46add2f20e783b32912e494 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.2 2006/12/23 04:56:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.3 2006/12/24 00:29:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #ifdef USE_LIBXML
 
-/*
- * A couple of useful macros (similar to ones from libxml/parse.c)
- */
-#define CMP4( s, c1, c2, c3, c4 ) \
-  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
-    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
-#define CMP5( s, c1, c2, c3, c4, c5 ) \
-  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
-
 #define PG_XML_DEFAULT_URI "dummy.xml"
 #define XML_ERRBUF_SIZE 200
 
@@ -177,31 +168,18 @@ xmlcomment(PG_FUNCTION_ARGS)
 
 
 Datum
-xmlparse(PG_FUNCTION_ARGS)
+texttoxml(PG_FUNCTION_ARGS)
 {
-#ifdef USE_LIBXML
-   text       *data;
-   bool        is_document;
-   bool        preserve_whitespace;
-
-   data = PG_GETARG_TEXT_P(0);
+   text       *data = PG_GETARG_TEXT_P(0);
 
-   if (PG_NARGS() >= 2)
-       is_document = PG_GETARG_BOOL(1);
-   else
-       is_document = false;
+   PG_RETURN_XML_P(xmlparse(data, false, true));
+}
 
-   if (PG_NARGS() >= 3)
-       preserve_whitespace = PG_GETARG_BOOL(2);
-   else
-       /*
-        * Since the XMLPARSE grammar makes STRIP WHITESPACE the
-        * default, this argument should really default to false.  But
-        * until we have actually implemented whitespace stripping,
-        * this would be annoying.
-        */
-       preserve_whitespace = true;
 
+xmltype *
+xmlparse(text *data, bool is_document, bool preserve_whitespace)
+{
+#ifdef USE_LIBXML
    if (!preserve_whitespace)
        ereport(WARNING,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -213,111 +191,93 @@ xmlparse(PG_FUNCTION_ARGS)
     * valies defined by internal DTD are applied'.  As for external
     * DTDs, we try to support them too, (see SQL/XML:10.16.7.e)
     */
-   xml_parse(data, XML_PARSE_DTDATTR, is_document); /* assume that ERROR occurred if parsing failed */
+   xml_parse(data, XML_PARSE_DTDATTR, is_document);
 
-   PG_RETURN_XML_P(data);
+   return (xmltype *) data;
 #else
    NO_XML_SUPPORT();
-   return 0;
+   return NULL;
 #endif
 }
 
 
-Datum
-xmlpi(PG_FUNCTION_ARGS)
+xmltype *
+xmlpi(char *target, text *arg)
 {
 #ifdef USE_LIBXML
-   char       *target = NameStr(*PG_GETARG_NAME(0));
+   xmltype *result;
    StringInfoData buf;
 
-   if (strlen(target) >= 3
-       && (target[0] == 'x' || target[0] == 'X')
-       && (target[1] == 'm' || target[1] == 'M')
-       && (target[2] == 'l' || target[2] == 'L'))
-   {
+   if (pg_strncasecmp(target, "xml", 3) == 0)
        ereport(ERROR,
-               (errcode(ERRCODE_SYNTAX_ERROR),
+               (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
                 errmsg("invalid XML processing instruction"),
                 errdetail("XML processing instruction target name cannot start with \"xml\".")));
-   }
 
    initStringInfo(&buf);
 
-   appendStringInfo(&buf, "<?");
-   appendStringInfoString(&buf, map_sql_identifier_to_xml_name(target, false));
-   if (PG_NARGS() > 1)
+   appendStringInfo(&buf, "<?%s", target);
+
+   if (arg != NULL)
    {
-       text *arg = PG_GETARG_TEXT_P(1);
        char *string;
 
-       string = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(arg)));
-       if (strstr(string, "?>"))
+       string = DatumGetCString(DirectFunctionCall1(textout,
+                                                    PointerGetDatum(arg)));
+       if (strstr(string, "?>") != NULL)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
                 errmsg("invalid XML processing instruction"),
                 errdetail("XML processing instruction cannot contain \"?>\".")));
 
-       appendStringInfoString(&buf, " ");
+       appendStringInfoChar(&buf, ' ');
        appendStringInfoString(&buf, string);
+       pfree(string);
    }
    appendStringInfoString(&buf, "?>");
 
-   PG_RETURN_XML_P(stringinfo_to_xmltype(&buf));
+   result = stringinfo_to_xmltype(&buf);
+   pfree(buf.data);
+   return result;
 #else
    NO_XML_SUPPORT();
-   return 0;
+   return NULL;
 #endif
 }
 
 
-Datum
-xmlroot(PG_FUNCTION_ARGS)
+xmltype *
+xmlroot(xmltype *data, text *version, int standalone)
 {
 #ifdef USE_LIBXML
-   xmltype    *data;
-   text       *version;
-   int         standalone;
+   xmltype *result;
    StringInfoData buf;
 
-   if (PG_ARGISNULL(0))
-       PG_RETURN_NULL();
-   else
-       data = PG_GETARG_XML_P(0);
-
-   if (PG_ARGISNULL(1))
-       version = NULL;
-   else
-       version = PG_GETARG_TEXT_P(1);
-
-   if (PG_ARGISNULL(2))
-       standalone = 0;
-   else
-   {
-       bool tmp = PG_GETARG_BOOL(2);
-       standalone = (tmp ? 1 : -1);
-   }
+   initStringInfo(&buf);
 
    /*
     * FIXME: This is probably supposed to be cleverer if there
     * already is an XML preamble.
     */
-   initStringInfo(&buf);
-
    appendStringInfo(&buf,"<?xml");
-   if (version) {
+   if (version)
+   {
        appendStringInfo(&buf, " version=\"");
        appendStringInfoText(&buf, version);
        appendStringInfo(&buf, "\"");
    }
    if (standalone)
-       appendStringInfo(&buf, " standalone=\"%s\"", (standalone == 1 ? "yes" : "no"));
+       appendStringInfo(&buf, " standalone=\"%s\"",
+                        (standalone == 1 ? "yes" : "no"));
    appendStringInfo(&buf, "?>");
    appendStringInfoText(&buf, (text *) data);
 
-   PG_RETURN_XML_P(stringinfo_to_xmltype(&buf));
+   result = stringinfo_to_xmltype(&buf);
+   pfree(buf.data);
+   return result;
 #else
    NO_XML_SUPPORT();
-   return 0;
+   return NULL;
 #endif
 }
 
@@ -456,7 +416,7 @@ xml_parse(text *data, int opts, bool is_document)
 
    /* first, we try to parse the string as XML doc, then, as XML chunk */
    ereport(DEBUG3, (errmsg("string to parse: %s", string)));
-   if (len > 4 && CMP5(string, '<', '?', 'x', 'm', 'l'))
+   if (len >= 5 && strncmp((char *) string, "<?xml", 5) == 0)
    {
        /* consider it as DOCUMENT */
        doc = xmlCtxtReadMemory(ctxt, (char *) string, len,
@@ -918,10 +878,8 @@ map_sql_identifier_to_xml_name(char *ident, bool fully_escaped)
            appendStringInfo(&buf, "_x003A_");
        else if (*p == '_' && *(p+1) == 'x')
            appendStringInfo(&buf, "_x005F_");
-       else if (fully_escaped && p == ident
-                && ( *p == 'x' || *p == 'X')
-                && ( *(p+1) == 'm' || *(p+1) == 'M')
-                && ( *(p+2) == 'l' || *(p+2) == 'L'))
+       else if (fully_escaped && p == ident &&
+                pg_strncasecmp(p, "xml", 3) == 0)
        {
            if (*p == 'x')
                appendStringInfo(&buf, "_x0078_");
@@ -932,9 +890,10 @@ map_sql_identifier_to_xml_name(char *ident, bool fully_escaped)
        {
            pg_wchar u = sqlchar_to_unicode(p);
 
-           if (!is_valid_xml_namechar(u)
-               || (p == ident && !is_valid_xml_namefirst(u)))
-           appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
+           if ((p == ident)
+               ? !is_valid_xml_namefirst(u)
+               : !is_valid_xml_namechar(u))
+               appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
            else
                appendBinaryStringInfo(&buf, p, pg_mblen(p));
        }
index f0a840a3ddef5d349d23362731a9968b3b167258..68f5a639347d493d242ba5a5e7ca4a9962251a34 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.365 2006/12/23 00:43:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.366 2006/12/24 00:29:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 200612221
+#define CATALOG_VERSION_NO 200612231
 
 #endif
index 974a2db360ca4c5eca15e02174296ba348be78f6..0a3ccc07f6cd541a7334cc5cae5fd4bf7e857ba4 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.431 2006/12/21 16:05:15 petere Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.432 2006/12/24 00:29:19 tgl Exp $
  *
  * NOTES
  *   The script catalog/genbki.sh reads this file and generates .bki
@@ -3983,17 +3983,9 @@ DATA(insert OID = 2894 (  xml_out           PGNSP PGUID 12 f f t f i 1 2275 "142" _nul
 DESCR("I/O");
 DATA(insert OID = 2895 (  xmlcomment      PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ xmlcomment - _null_ ));
 DESCR("generate an XML comment");
-DATA(insert OID = 2896 (  xmlparse        PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ xmlparse - _null_ ));
+DATA(insert OID = 2896 (  xml             PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ texttoxml - _null_ ));
 DESCR("perform a non-validating parse of a character string to produce an XML value");
-DATA(insert OID = 2897 (  xmlparse        PGNSP PGUID 12 f f t f i 3 142 "25 16 16" _null_ _null_ _null_ xmlparse - _null_ ));
-DESCR("perform a non-validating parse of a character string to produce an XML value");
-DATA(insert OID = 2898 (  xmlpi               PGNSP PGUID 12 f f t f i 1 142 "19" _null_ _null_ _null_ xmlpi - _null_ ));
-DESCR("generate an XML processing instruction");
-DATA(insert OID = 2899 (  xmlpi               PGNSP PGUID 12 f f t f i 2 142 "19 25" _null_ _null_ _null_ xmlpi - _null_ ));
-DESCR("generate an XML processing instruction");
-DATA(insert OID = 2900 (  xmlroot         PGNSP PGUID 12 f f f f i 3 142 "142 25 16" _null_ _null_ _null_ xmlroot - _null_ ));
-DESCR("create an XML value by modifying the properties of the XML root information item of another XML value");
-DATA(insert OID = 2901 (  xmlvalidate     PGNSP PGUID 12 f f t f i 2 16 "142 25" _null_ _null_ _null_ xmlvalidate - _null_ ));
+DATA(insert OID = 2897 (  xmlvalidate     PGNSP PGUID 12 f f t f i 2 16 "142 25" _null_ _null_ _null_ xmlvalidate - _null_ ));
 DESCR("validate an XML value");
 
 /*
index 1db920aa0c1b0c4836c5b3e32b9d9ea564b123b9..f8e8f15a5dba916194f2b556a51c3d629b5f0579 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.163 2006/12/21 16:05:16 petere Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.164 2006/12/24 00:29:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -710,6 +710,18 @@ typedef struct MinMaxExprState
    FmgrInfo    cfunc;          /* lookup info for comparison func */
 } MinMaxExprState;
 
+/* ----------------
+ *     XmlExprState node
+ * ----------------
+ */
+typedef struct XmlExprState
+{
+   ExprState   xprstate;
+   List       *named_args;     /* ExprStates for named arguments */
+   FmgrInfo   *named_outfuncs; /* array of output fns for named arguments */
+   List       *args;           /* ExprStates for other arguments */
+} XmlExprState;
+
 /* ----------------
  *     NullTestState node
  * ----------------
@@ -723,22 +735,6 @@ typedef struct NullTestState
    TupleDesc   argdesc;        /* tupdesc for most recent input */
 } NullTestState;
 
-/* ----------------
- *     XmlExprState node
- * ----------------
- */
-typedef struct XmlExprState
-{
-   ExprState   xprstate;
-   XmlExprOp   op;
-   char       *name;
-   List       *named_args;
-   List       *args;
-   Oid        *named_args_tcache;
-   char      **named_args_ncache;
-   Oid         arg_typeout;
-} XmlExprState;
-
 /* ----------------
  *     CoerceToDomainState node
  * ----------------
index eb6ba18adab390357a05f9865d3b98b570b92b11..fa9dff9d961ba8f7857a31001b80201cf88f10c7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.189 2006/12/21 16:05:16 petere Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.190 2006/12/24 00:29:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -130,6 +130,7 @@ typedef enum NodeTag
    T_RowCompareExpr,
    T_CoalesceExpr,
    T_MinMaxExpr,
+   T_XmlExpr,
    T_NullIfExpr,
    T_NullTest,
    T_BooleanTest,
@@ -140,7 +141,6 @@ typedef enum NodeTag
    T_RangeTblRef,
    T_JoinExpr,
    T_FromExpr,
-   T_XmlExpr,
 
    /*
     * TAGS FOR EXPRESSION STATE NODES (execnodes.h)
@@ -166,10 +166,10 @@ typedef enum NodeTag
    T_RowCompareExprState,
    T_CoalesceExprState,
    T_MinMaxExprState,
+   T_XmlExprState,
    T_NullTestState,
    T_CoerceToDomainState,
    T_DomainConstraintState,
-   T_XmlExprState,
 
    /*
     * TAGS FOR PLANNER NODES (relation.h)
index 5946300c9751fdc4a359dc421a8a6b8dce53f4f2..bd2c39040fc1253853650eeed5dbd43e51fc967d 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.120 2006/12/23 00:43:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.121 2006/12/24 00:29:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -711,6 +711,33 @@ typedef struct MinMaxExpr
    List       *args;           /* the arguments */
 } MinMaxExpr;
 
+/*
+ * XmlExpr - various SQL/XML functions requiring special grammar productions
+ *
+ * 'name' carries the "NAME foo" argument (already XML-escaped).
+ * 'named_args' and 'arg_names' represent an xml_attribute list.
+ * 'args' carries all other arguments.
+ */
+typedef enum XmlExprOp
+{
+   IS_XMLCONCAT,               /* XMLCONCAT(args) */
+   IS_XMLELEMENT,              /* XMLELEMENT(name, xml_attributes, args) */
+   IS_XMLFOREST,               /* XMLFOREST(xml_attributes) */
+   IS_XMLPARSE,                /* XMLPARSE(text, is_doc, preserve_ws) */
+   IS_XMLPI,                   /* XMLPI(name [, args]) */
+   IS_XMLROOT                  /* XMLROOT(xml, version, standalone) */
+} XmlExprOp;
+
+typedef struct XmlExpr
+{
+   Expr        xpr;
+   XmlExprOp   op;             /* xml function ID */
+   char       *name;           /* name in xml(NAME foo ...) syntaxes */
+   List       *named_args;     /* non-XML expressions for xml_attributes */
+   List       *arg_names;      /* parallel list of Value strings */
+   List       *args;           /* list of expressions */
+} XmlExpr;
+
 /*
  * NullIfExpr - a NULLIF expression
  *
@@ -765,26 +792,6 @@ typedef struct BooleanTest
    BoolTestType booltesttype;  /* test type */
 } BooleanTest;
 
-/*
- * XmlExpr - holder for SQL/XML functions XMLCONCAT,
- * XMLELEMENT, XMLFOREST
- */
-typedef enum XmlExprOp
-{
-   IS_XMLCONCAT,
-   IS_XMLELEMENT,
-   IS_XMLFOREST,
-} XmlExprOp;
-
-typedef struct XmlExpr
-{
-   Expr        xpr;
-   XmlExprOp   op;             /* xml expression type */
-   char       *name;           /* element name */
-   List       *named_args;
-   List       *args;
-} XmlExpr;
-
 /*
  * CoerceToDomain
  *
index 9c077095e9e563822fff96fd50244bb74fec66f7..08573abd1ef422a9e75b34e7c682c3a1bf4c1ae2 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.67 2006/12/21 16:05:16 petere Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.68 2006/12/24 00:29:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,12 +55,9 @@ extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod,
 
 extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
                  const char *constructName);
-extern Node *coerce_to_integer(ParseState *pstate, Node *node,
-                 const char *constructName);
-extern Node *coerce_to_bigint(ParseState *pstate, Node *node,
-                const char *constructName);
-extern Node *coerce_to_xml(ParseState *pstate, Node *node,
-                const char *constructName);
+extern Node *coerce_to_specific_type(ParseState *pstate, Node *node,
+                                    Oid targetTypeId,
+                                    const char *constructName);
 
 extern Oid select_common_type(List *typeids, const char *context);
 extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
index a353d8837c93268aff4acd8aec7045ae8aef7804..713bdaeb115259f402ed1e62909a1f49543bc05b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.2 2006/12/23 04:56:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.3 2006/12/24 00:29:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,11 +27,13 @@ typedef struct varlena xmltype;
 extern Datum xml_in(PG_FUNCTION_ARGS);
 extern Datum xml_out(PG_FUNCTION_ARGS);
 extern Datum xmlcomment(PG_FUNCTION_ARGS);
-extern Datum xmlparse(PG_FUNCTION_ARGS);
-extern Datum xmlpi(PG_FUNCTION_ARGS);
-extern Datum xmlroot(PG_FUNCTION_ARGS);
+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 *xmlroot(xmltype *data, text *version, int standalone);
+
 extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped);
 
 #endif /* XML_H */
index c28c2c6c8f3597a5535029b383afb6c3c23bc94e..bff815206169bc37e874743d859accc4aeaf6e19 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.180 2006/10/04 00:30:13 momjian Exp $
+ *   $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.181 2006/12/24 00:29:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -4493,6 +4493,18 @@ exec_simple_check_node(Node *node)
                return TRUE;
            }
 
+       case T_XmlExpr:
+           {
+               XmlExpr *expr = (XmlExpr *) node;
+
+               if (!exec_simple_check_node((Node *) expr->named_args))
+                   return FALSE;
+               if (!exec_simple_check_node((Node *) expr->args))
+                   return FALSE;
+
+               return TRUE;
+           }
+
        case T_NullIfExpr:
            {
                NullIfExpr *expr = (NullIfExpr *) node;
index 478bf3b080683a8ca5526c450c198291946b465c..ba0c229ccd14be2d30d8ad71e6b72cab22fd1397 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Copyright (c) 2003-2006, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/plerrcodes.h,v 1.9 2006/06/16 23:29:27 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/plerrcodes.h,v 1.10 2006/12/24 00:29:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    "untranslatable_character", ERRCODE_UNTRANSLATABLE_CHARACTER
 },
 
+{
+   "invalid_xml_document", ERRCODE_INVALID_XML_DOCUMENT
+},
+
+{
+   "invalid_xml_content", ERRCODE_INVALID_XML_CONTENT
+},
+
+{
+   "invalid_xml_comment", ERRCODE_INVALID_XML_COMMENT
+},
+
+{
+   "invalid_xml_processing_instruction", ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION
+},
+
 {
    "integrity_constraint_violation", ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION
 },
index a0e9483ebd0b172d65474078b1e34175670b7e21..7bfa35a46f8c4c25e5c1059ca8ed2d9d40e3e962 100644 (file)
@@ -74,7 +74,7 @@ WHERE p1.oid != p2.oid AND
 SELECT p1.oid, p1.proname, p2.oid, p2.proname
 FROM pg_proc AS p1, pg_proc AS p2
 WHERE p1.oid < p2.oid AND
-    p1.prosrc = p2.prosrc AND p1.prosrc NOT IN ('xmlparse', 'xmlpi') AND
+    p1.prosrc = p2.prosrc AND
     p1.prolang = 12 AND p2.prolang = 12 AND
     (p1.proisagg = false OR p2.proisagg = false) AND
     (p1.prolang != p2.prolang OR
index 4dd39eb164e8ed8a5717ccce590e194b83c8609a..b8c184f784b41804cca26365792c36fab55e63cd 100644 (file)
@@ -77,7 +77,7 @@ WHERE p1.oid != p2.oid AND
 SELECT p1.oid, p1.proname, p2.oid, p2.proname
 FROM pg_proc AS p1, pg_proc AS p2
 WHERE p1.oid < p2.oid AND
-    p1.prosrc = p2.prosrc AND p1.prosrc NOT IN ('xmlparse', 'xmlpi') AND
+    p1.prosrc = p2.prosrc AND
     p1.prolang = 12 AND p2.prolang = 12 AND
     (p1.proisagg = false OR p2.proisagg = false) AND
     (p1.prolang != p2.prolang OR