Hi hackers,

The namespace URI in XMLNAMESPACES is a b_expr in the grammar, so an
expression with a COLLATE clause has to be in parentheses there.
Pretty-printed output leaves them out, so the definition of a view
using one cannot be read back.  The two attached patches add a test
and fix it.

The problem
-----------

    create view v as
      select * from xmltable(
        xmlnamespaces(('http://x.y' collate "C") as p),
        '/p:a' passing (null::xml) columns v text path 'p:b');

    before:  XMLNAMESPACES ('http://x.y'::text COLLATE "C" AS p)
             ERROR:  syntax error at or near "COLLATE"
    after:   XMLNAMESPACES (('http://x.y'::text COLLATE "C") AS p)

Only pretty-printed output is affected, such as pg_get_viewdef(...,
true) and psql's \d+.  Outside pretty mode the COLLATE expression
prints its own parentheses, so pg_dump is fine.

The fix
-------

get_xmltable() printed the URI with get_rule_expr() as it was.  0002
puts it in parentheses, after XMLNAMESPACES( as well as after DEFAULT,
unless it is a plain Const.  A constant is the usual case and needs
none, so its output does not change.  Any other expression gets them
even where it would not need them, such as an operator expression;
that output read back before and still does.  This is what ruleutils.c
already does for b_expr and c_expr arguments elsewhere, such as those
of POSITION and XMLEXISTS.

Outside pretty mode such a URI now gets two pairs of parentheses,
because the COLLATE expression prints its own there.  That is how
other operands are printed in that mode, and it reads back.

Testing
-------

0001 adds a view to xml.sql, prints it with pg_get_viewdef(..., true)
and recreates the view from that output.  0001 has the output before
the fix, where the recreation fails, and 0002 updates it.

Back branches
-------------

XMLNAMESPACES has been printed this way since XMLTABLE came in 10, so
I think this should be fixed back to 14.  The code change applies to
14-19 as is.  The test applies to 17 and later; in 14-16 it needs
another place in xml.sql, and its expected output may differ.

This came out of the same AI-assisted audit of ruleutils.c as my
earlier [DEPARSE] reports.

Best regards,
Henson

Attachment: v1-0001-Add-a-test-for-a-COLLATE-clause-in-the-URI.patch
Description: Binary data

Attachment: v1-0002-Parenthesize-the-URI-of-XMLNAMESPACES.patch
Description: Binary data

Reply via email to