| From: | Henson Choi <assam258(at)gmail(dot)com> |
|---|---|
| To: | pgsql-hackers <pgsql-hackers(at)postgresql(dot)org> |
| Subject: | [DEPARSE] IS DOCUMENT as an operand loses needed parentheses |
| Date: | 2026-10-14 01:10:40 |
| Message-ID: | CAAAe_zDuPSkc8ihCctV67Lxbqock+S4wqCHHo8xxZ1t4teXo0g@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi hackers,
ruleutils.c treats x IS DOCUMENT as a self-delimiting,
function-like expression, like xmlelement(...). It is really a
postfix test like IS NULL, so printed as the operand of another
expression it loses the parentheses it needs. The text then reads
back as another expression, or is rejected. This happens outside
pretty mode too, so pg_dump output cannot be restored when such an
object exists. The two attached patches add tests and fix it.
The problem
-----------
In a view or rule, with IS DOCUMENT as the right operand of an
operator:
create table t (f bool, x xml);
create view v as select f = (x is document) as r1 from t;
non-pretty, before: SELECT (f = x IS DOCUMENT) AS r1
pretty, before: SELECT f = (x) IS DOCUMENT AS r1
both read back as (f = x) IS DOCUMENT:
ERROR: operator does not exist: boolean = xml
after: SELECT (f = (x IS DOCUMENT)) AS r1
SELECT f = (x IS DOCUMENT) AS r1
Index expressions, partition keys and extended statistics
expressions can be written without parentheses only if they are
function-like, and looks_like_function() says IS DOCUMENT is:
create index i on t ((x is document));
before: CREATE INDEX i ON public.t USING btree (x IS DOCUMENT)
ERROR: syntax error at or near "IS"
after: ... USING btree (((x IS DOCUMENT)))
partition by list ((x is document))
before: LIST (x IS DOCUMENT) -- same syntax error
after: LIST (((x IS DOCUMENT)))
create statistics s on (x is document), f from t;
before: ... ON f, (x) IS DOCUMENT FROM t -- syntax error
after: ... ON f, (x IS DOCUMENT) FROM t
CHECK constraints, column defaults and generated columns, trigger
WHEN conditions, policies, SQL-standard function bodies and
publication row filters go through the same code, and fail to
restore in the same way.
The fix
-------
0002 treats IS DOCUMENT like the other postfix tests.
- isSimpleNode(): takes IS DOCUMENT, and only it among the
XmlExprs, out of the function-like list, so that it is
judged like IS NULL.
- looks_like_function(): returns false for IS DOCUMENT. The other
XmlExprs (XMLCONCAT, XMLELEMENT, ...) stay function-like.
- get_rule_expr(): prints parentheses of its own outside pretty
mode, as IS NULL does. It also passes the single argument to
get_rule_expr_paren(), not the argument list, which is what gave
the needless parentheses of (x) IS DOCUMENT in pretty mode.
Outside pretty mode, IS DOCUMENT as the argument of a cast now
gets a second pair of parentheses, ((x IS DOCUMENT))::text. The
other postfix tests and operator expressions are already printed
that way, as in ((a IS NULL))::text, so this only makes the output
consistent, and it reads back the same.
Testing
-------
0001 adds the tests with the output before the fix, and 0002
updates it, so that the diff shows what changes. The view is
created again from its non-pretty text, and the statistics object
and the index from their printed definitions.
Some output still has more parentheses than it needs, such as
(((x IS DOCUMENT))) in a non-pretty index definition. That is not
specific to IS DOCUMENT: other postfix tests are printed the same
way there. I will approach it in a separate patch.
Back branches
-------------
I think this should be back-patched to 15. I applied both patches
to REL_15_STABLE through REL_19_STABLE.
The patches apply cleanly to REL_19 and pass make check. The
older branches need small adjustments: /* FALLTHROUGH */ in
place of pg_fallthrough (15-18), some hunks moved by hand
(15, 16) and, on 15, regenerated expected test output. With
those, all branches pass.
This came out of an AI-assisted audit of ruleutils.c. I will
post the other problems it found as separate, independent reports
as I work through them.
Best regards,
Henson
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Add-tests-for-IS-DOCUMENT.patch | application/x-patch | 5.8 KB |
| v1-0002-Parenthesize-IS-DOCUMENT.patch | application/x-patch | 8.6 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Henson Choi | 2026-10-14 01:10:42 | [DEPARSE] Operators on ROW() constructors read back as row comparisons |
| Previous Message | Min, Baohong | 2026-10-14 01:05:00 | RE: [PATCH] Reduce LWLockWaitListLock() cache-line contention with adaptive spin reads |