From 5c92b4beca25b0938fd0fda19d890999b36fb905 Mon Sep 17 00:00:00 2001 From: meskill <8974488+meskill@users.noreply.github.com> Date: Thu, 24 Sep 2026 12:34:16 +0000 Subject: [PATCH 1/2] test: deparse timezone --- BUGS.md | 20 ++++++++++++++++++++ src/deparse.rs | 7 +++++++ 2 files changed, 27 insertions(+) diff --git a/BUGS.md b/BUGS.md index d2ffd60..e3a94d9 100644 --- a/BUGS.md +++ b/BUGS.md @@ -11,3 +11,23 @@ libpg_query deparses the argument as `offset int`, which is invalid because `OFFSET` is reserved. `deparseFunctionParameter` in `libpg_query/src/postgres_deparse.c` should call `quote_identifier` for parameter names. + +## Missing parentheses around the `AT TIME ZONE` zone operand + +```sql +SELECT ts AT TIME ZONE ((summary -> 'stop') ->> 'tz') FROM s; +``` + +libpg_query deparses this as `ts AT TIME ZONE (summary -> 'stop') ->> 'tz'`, then +drops the remaining parentheses on the next round trip. `AT` binds tighter than +`Op`, so the result parses as `(ts AT TIME ZONE summary) -> 'stop' ->> 'tz'` and +fails with `function pg_catalog.timezone(jsonb, timestamp with time zone) does +not exist`. + +The `pg_catalog.timezone` branch of `deparseFuncCall` in +`libpg_query/src/postgres_deparse.c` parenthesises the timestamp operand when it +is an `A_Expr`, but writes the zone operand without that check. The zone operand +needs the same `IsA(zone, A_Expr)` parentheses. + +`test_deparse` in `src/deparse.rs` covers this. The test fails until libpg_query +ships the fix. diff --git a/src/deparse.rs b/src/deparse.rs index 5601247..d289212 100644 --- a/src/deparse.rs +++ b/src/deparse.rs @@ -87,4 +87,11 @@ fn test_deparse() { run_test("DELETE FROM users WHERE id = 1"); run_test("SET my_config TO 1"); run_test("TRUNCATE users"); + run_test("SELECT ts AT TIME ZONE tz FROM s"); + run_test("SELECT (ts -> 'a') AT TIME ZONE tz FROM s"); + run_test("SELECT ts AT TIME ZONE (a -> 'b') FROM s"); + run_test("SELECT ts AT TIME ZONE (tz || 'x') FROM s"); + run_test( + "SELECT ((summary ->> 'ts')::timestamptz AT TIME ZONE ((summary -> 'stop') ->> 'tz'))::date AS d FROM s", + ); } From ebb4b03cbe11a86174d5c08c2f838934c3235d11 Mon Sep 17 00:00:00 2001 From: meskill <8974488+meskill@users.noreply.github.com> Date: Thu, 24 Sep 2026 14:18:05 +0000 Subject: [PATCH 2/2] fix(deparse): use fork --- .gitmodules | 4 +++- BUGS.md | 20 -------------------- libpg_query | 2 +- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/.gitmodules b/.gitmodules index ab4faf9..caa3a63 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,5 @@ [submodule "libpg_query"] path = libpg_query - url = https://github.com/pganalyze/libpg_query + # TODO: rollback to original repo after merge https://github.com/pganalyze/libpg_query/pull/368 + url = https://github.com/meskill/libpg_query + branch = fix-at-time-paranses diff --git a/BUGS.md b/BUGS.md index e3a94d9..d2ffd60 100644 --- a/BUGS.md +++ b/BUGS.md @@ -11,23 +11,3 @@ libpg_query deparses the argument as `offset int`, which is invalid because `OFFSET` is reserved. `deparseFunctionParameter` in `libpg_query/src/postgres_deparse.c` should call `quote_identifier` for parameter names. - -## Missing parentheses around the `AT TIME ZONE` zone operand - -```sql -SELECT ts AT TIME ZONE ((summary -> 'stop') ->> 'tz') FROM s; -``` - -libpg_query deparses this as `ts AT TIME ZONE (summary -> 'stop') ->> 'tz'`, then -drops the remaining parentheses on the next round trip. `AT` binds tighter than -`Op`, so the result parses as `(ts AT TIME ZONE summary) -> 'stop' ->> 'tz'` and -fails with `function pg_catalog.timezone(jsonb, timestamp with time zone) does -not exist`. - -The `pg_catalog.timezone` branch of `deparseFuncCall` in -`libpg_query/src/postgres_deparse.c` parenthesises the timestamp operand when it -is an `A_Expr`, but writes the zone operand without that check. The zone operand -needs the same `IsA(zone, A_Expr)` parentheses. - -`test_deparse` in `src/deparse.rs` covers this. The test fails until libpg_query -ships the fix. diff --git a/libpg_query b/libpg_query index 204fbdb..7379642 160000 --- a/libpg_query +++ b/libpg_query @@ -1 +1 @@ -Subproject commit 204fbdbd3ed5f8691ab358e49f1fc5397b4679e2 +Subproject commit 73796421fbecca29967b458a79b319982a8bee2a