From 3c1f6a3d1b683a9d5ab4a86c85d6c4ed6e9a0b31 Mon Sep 17 00:00:00 2001 From: Henson Choi Date: Tue, 13 Oct 2026 14:55:16 +0900 Subject: [PATCH v1 1/2] Add tests for a relation alias named SET in DML targets An alias named "set" on the target of UPDATE, DELETE or MERGE is printed bare and read back as the SET keyword. The expected output shows the behavior before the fix. The next commit fixes it and updates the output. --- src/test/regress/expected/rules.out | 102 ++++++++++++++++++++++++++++ src/test/regress/sql/rules.sql | 48 +++++++++++++ 2 files changed, 150 insertions(+) diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 4addeba2508..e7aa49de416 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -4153,3 +4153,105 @@ DROP TABLE ruletest_t3; DROP TABLE ruletest_t2; DROP TABLE ruletest_t1; DROP USER regress_rule_user1; +-- +-- An UPDATE, DELETE or MERGE target alias named "set" must be printed with +-- AS, since a bare "set" would be taken as the SET keyword +-- +create table ruletest_setalias (a int, b int); +create rule ruletest_setalias_r1 as on insert to ruletest_setalias + do also update ruletest_setalias "set" set b = 1 where "set".a = 2; +create rule ruletest_setalias_r2 as on insert to ruletest_setalias + do also delete from ruletest_setalias "set" where "set".a = 1; +select rulename, pg_get_ruledef(oid) from pg_rewrite + where rulename like 'ruletest_setalias_r%' order by rulename; + rulename | pg_get_ruledef +----------------------+-------------------------------------------------------------------------------------- + ruletest_setalias_r1 | CREATE RULE ruletest_setalias_r1 AS + + | ON INSERT TO public.ruletest_setalias DO UPDATE ruletest_setalias set SET b = 1+ + | WHERE (set.a = 2); + ruletest_setalias_r2 | CREATE RULE ruletest_setalias_r2 AS + + | ON INSERT TO public.ruletest_setalias DO DELETE FROM ruletest_setalias set + + | WHERE (set.a = 1); +(2 rows) + +select pg_get_ruledef(oid) as def from pg_rewrite + where rulename = 'ruletest_setalias_r1' \gset +drop rule ruletest_setalias_r1 on ruletest_setalias; +:def +ERROR: syntax error at or near "b" +LINE 2: ...ruletest_setalias DO UPDATE ruletest_setalias set SET b = 1 + ^ +select pg_get_ruledef(oid) from pg_rewrite + where rulename = 'ruletest_setalias_r1'; + pg_get_ruledef +---------------- +(0 rows) + +select pg_get_ruledef(oid) as def from pg_rewrite + where rulename = 'ruletest_setalias_r2' \gset +drop rule ruletest_setalias_r2 on ruletest_setalias; +:def +ERROR: syntax error at or near "set" +LINE 2: ...blic.ruletest_setalias DO DELETE FROM ruletest_setalias set + ^ +select pg_get_ruledef(oid) from pg_rewrite + where rulename = 'ruletest_setalias_r2'; + pg_get_ruledef +---------------- +(0 rows) + +create table ruletest_setalias_m (a int, b int); +create table ruletest_setalias_src (a int); +create function ruletest_setalias_f() returns void language sql +begin atomic + merge into ruletest_setalias_m "set" + using ruletest_setalias_src s on "set".a = s.a + when matched then update set b = 1; +end; +select pg_get_functiondef('ruletest_setalias_f'::regproc); + pg_get_functiondef +--------------------------------------------------------- + CREATE OR REPLACE FUNCTION public.ruletest_setalias_f()+ + RETURNS void + + LANGUAGE sql + + BEGIN ATOMIC + + MERGE INTO ruletest_setalias_m set + + USING ruletest_setalias_src s + + ON (set.a = s.a) + + WHEN MATCHED + + THEN UPDATE SET b = 1; + + END + + +(1 row) + +select pg_get_functiondef('ruletest_setalias_f'::regproc) as def \gset +drop function ruletest_setalias_f(); +:def; +ERROR: syntax error at or near "set" +LINE 5: MERGE INTO ruletest_setalias_m set + ^ +select pg_get_functiondef(oid) from pg_proc + where proname = 'ruletest_setalias_f'; + pg_get_functiondef +-------------------- +(0 rows) + +-- A FROM-clause alias named "set" does not need AS +create view ruletest_setalias_v as + select "set".a from ruletest_setalias_m "set", ruletest_setalias_src s + where "set".a = s.a; +select pg_get_viewdef('ruletest_setalias_v'::regclass); + pg_get_viewdef +---------------------------------- + SELECT set.a + + FROM ruletest_setalias_m set,+ + ruletest_setalias_src s + + WHERE (set.a = s.a); +(1 row) + +drop view ruletest_setalias_v; +drop function ruletest_setalias_f(); +ERROR: function ruletest_setalias_f() does not exist +drop table ruletest_setalias_src; +drop table ruletest_setalias_m; +drop table ruletest_setalias; diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql index abe89d097c9..866f5e6a3dc 100644 --- a/src/test/regress/sql/rules.sql +++ b/src/test/regress/sql/rules.sql @@ -1460,3 +1460,51 @@ DROP TABLE ruletest_t2; DROP TABLE ruletest_t1; DROP USER regress_rule_user1; + +-- +-- An UPDATE, DELETE or MERGE target alias named "set" must be printed with +-- AS, since a bare "set" would be taken as the SET keyword +-- +create table ruletest_setalias (a int, b int); +create rule ruletest_setalias_r1 as on insert to ruletest_setalias + do also update ruletest_setalias "set" set b = 1 where "set".a = 2; +create rule ruletest_setalias_r2 as on insert to ruletest_setalias + do also delete from ruletest_setalias "set" where "set".a = 1; +select rulename, pg_get_ruledef(oid) from pg_rewrite + where rulename like 'ruletest_setalias_r%' order by rulename; +select pg_get_ruledef(oid) as def from pg_rewrite + where rulename = 'ruletest_setalias_r1' \gset +drop rule ruletest_setalias_r1 on ruletest_setalias; +:def +select pg_get_ruledef(oid) from pg_rewrite + where rulename = 'ruletest_setalias_r1'; +select pg_get_ruledef(oid) as def from pg_rewrite + where rulename = 'ruletest_setalias_r2' \gset +drop rule ruletest_setalias_r2 on ruletest_setalias; +:def +select pg_get_ruledef(oid) from pg_rewrite + where rulename = 'ruletest_setalias_r2'; +create table ruletest_setalias_m (a int, b int); +create table ruletest_setalias_src (a int); +create function ruletest_setalias_f() returns void language sql +begin atomic + merge into ruletest_setalias_m "set" + using ruletest_setalias_src s on "set".a = s.a + when matched then update set b = 1; +end; +select pg_get_functiondef('ruletest_setalias_f'::regproc); +select pg_get_functiondef('ruletest_setalias_f'::regproc) as def \gset +drop function ruletest_setalias_f(); +:def; +select pg_get_functiondef(oid) from pg_proc + where proname = 'ruletest_setalias_f'; +-- A FROM-clause alias named "set" does not need AS +create view ruletest_setalias_v as + select "set".a from ruletest_setalias_m "set", ruletest_setalias_src s + where "set".a = s.a; +select pg_get_viewdef('ruletest_setalias_v'::regclass); +drop view ruletest_setalias_v; +drop function ruletest_setalias_f(); +drop table ruletest_setalias_src; +drop table ruletest_setalias_m; +drop table ruletest_setalias; -- 2.54.0 (Apple Git-157)