| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | alpkeles99(at)gmail(dot)com |
| Subject: | BUG #19767: pg_get_viewdef prints ORDER BY (- '3'::int4) as (- 3), which reparses as column position -3 |
| Date: | 2026-10-16 15:59:56 |
| Message-ID: | 19767-f1189fd6a83254b7@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19767
Logged by: Alperen Keles
Email address: alpkeles99(at)gmail(dot)com
PostgreSQL version: 18.6
Operating system: Ubuntu 24.04 x86_64 (also macOS 26 arm64)
Description:
Hello,
In ORDER BY and GROUP BY, a bare integer constant is a column position
(ORDER BY 2), while "ORDER BY (- '3'::int4)" is an expression, the negation
of a typed literal, so it sorts by a constant -3.
pg_get_viewdef() prints that term as "(- 3)". When that text is parsed
again, the grammar folds "- 3" into the integer constant -3 (doNegate),
which ORDER BY then reads as a column position. So the printed
definition of a valid view is not a valid view, and pg_dump, which
prints views the same way, writes a dump that does not restore.
```
CREATE TABLE t (a int);
INSERT INTO t VALUES (1), (2);
CREATE VIEW o AS SELECT a FROM t ORDER BY (- '3'::int4);
CREATE VIEW g AS SELECT count(*) AS n FROM t GROUP BY (- '3'::int4);
SELECT * FROM o; -- 1, 2
SELECT * FROM g; -- 2
SELECT pg_get_viewdef('o'::regclass);
SELECT a
FROM t
ORDER BY (- 3);
SELECT pg_get_viewdef('g'::regclass);
SELECT count(*) AS n
FROM t
GROUP BY (- 3);
```
Creating each view again from its own printed definition fails:
```
CREATE VIEW o2 AS SELECT a FROM t ORDER BY (- 3);
ERROR: ORDER BY position -3 is not in select list
CREATE VIEW g2 AS SELECT count(*) AS n FROM t GROUP BY (- 3);
ERROR: GROUP BY position -3 is not in select list
```
That is what happens on restore: pg_dump of that database writes
```
CREATE VIEW public.o AS
SELECT a
FROM public.t
ORDER BY (- 3);
```
and restoring it with psql into an empty database gives
```
psql:dump.sql:44: ERROR: ORDER BY position -3 is not in select list
psql:dump.sql:67: ERROR: GROUP BY position -3 is not in select list
```
followed by "relation does not exist" for the views' ALTER OWNER and for
a view built on top of o, so those views are lost. pg_restore of a -Fc
dump fails the same way.
When the folded constant is a position that exists, the text silently
means something else. "- (- '1'::int4)" prints as "(- (- 1))", which
folds to 1:
```
CREATE TABLE t2 (a int, b int);
INSERT INTO t2 VALUES (1, 10), (2, 20), (1, 30);
CREATE VIEW v AS SELECT DISTINCT ON (- (- '1'::int4)) a, b FROM t2
ORDER BY - (- '1'::int4), b DESC;
SELECT * FROM v; -- one row: (1,30)
```
Its definition, run again (or restored from a dump), becomes
DISTINCT ON (a) ... ORDER BY a, b DESC and returns (1,30) and (2,20).
Reproduced on 18.6 (REL_18_STABLE dfbc1507cdb), 19rc1 (REL_19_STABLE
1212d5d33b1), 14.24 (REL_14_STABLE 14904052e65) and master a261fc2b722,
Ubuntu 24.04 x86_64, --enable-cassert, with pg_dump of the same version;
also on 18.6 and master on macOS arm64.
Found with a query fuzzer.
Regards,
Alperen Keles
| From | Date | Subject | |
|---|---|---|---|
| Previous Message | PG Bug reporting form | 2026-10-16 15:24:16 | BUG #19766: Assert in shm_toc_insert: EXPLAIN ANALYZE of a SubPlan shared by Parallel Append children |