diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2025-01-08 16:35:54 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2025-01-08 16:35:54 -0500 |
commit | 3c49d462dbcfaff7bb77b1fec2c73c1079d25433 (patch) | |
tree | 378658ea6d75c8faec5b0dd16a8f065a8dc291ec | |
parent | b20fe54c9c2194fec65db73b2778a014e7823ae0 (diff) | |
download | postgresql-3c49d462dbcfaff7bb77b1fec2c73c1079d25433.tar.gz postgresql-3c49d462dbcfaff7bb77b1fec2c73c1079d25433.zip |
Disallow NAMEDTUPLESTORE RTEs in stored views, rules, etc.
A named tuplestore is necessarily a transient object, so it makes
no sense to reference one in a persistent object such as a view.
We didn't previously prevent that, with the result that if you
tried you would get some weird failure about how the executor
couldn't find the tuplestore.
We can mechanize a check for this case cheaply by making dependency
extraction complain if it comes across such an RTE. This is a
plausible way of dealing with it since part of the problem is that we
have no way to make a pg_depend representation of a named tuplestore.
Report and fix by Yugo Nagata. Although this is an old problem,
it's a very weird corner case and there have been no reports from
end users. So it seems sufficient to fix it in master.
Discussion: https://postgr.es/m/20240726160714.e74d0db579f2c017e1ca0b7e@sraoss.co.jp
-rw-r--r-- | src/backend/catalog/dependency.c | 15 | ||||
-rw-r--r-- | src/test/regress/expected/triggers.out | 20 | ||||
-rw-r--r-- | src/test/regress/sql/triggers.sql | 19 |
3 files changed, 54 insertions, 0 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 096b68c7f39..18316a3968b 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2191,7 +2191,22 @@ find_expr_references_walker(Node *node, } context->rtables = list_delete_first(context->rtables); break; + case RTE_NAMEDTUPLESTORE: + + /* + * Cataloged objects cannot depend on tuplestores, because + * those have no cataloged representation. For now we can + * call the tuplestore a "transition table" because that's + * the only kind exposed to SQL, but someday we might have + * to work harder. + */ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("transition table \"%s\" cannot be referenced in a persistent object", + rte->eref->aliasname))); + break; default: + /* Other RTE types can be ignored here */ break; } } diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index a044d6afe27..0657da17577 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -3315,6 +3315,26 @@ create trigger my_table_col_update_trig ERROR: transition tables cannot be specified for triggers with column lists drop table my_table; -- +-- Verify that transition tables can't be used in, eg, a view. +-- +create table my_table (a int); +create function make_bogus_matview() returns trigger as +$$ begin + create materialized view transition_test_mv as select * from new_table; + return new; +end $$ +language plpgsql; +create trigger make_bogus_matview + after insert on my_table + referencing new table as new_table + for each statement execute function make_bogus_matview(); +insert into my_table values (42); -- error +ERROR: transition table "new_table" cannot be referenced in a persistent object +CONTEXT: SQL statement "create materialized view transition_test_mv as select * from new_table" +PL/pgSQL function make_bogus_matview() line 2 at SQL statement +drop table my_table; +drop function make_bogus_matview(); +-- -- Test firing of triggers with transition tables by foreign key cascades -- create table refd_table (a int primary key, b text); diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index 51610788b21..7e2f7597c10 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -2435,6 +2435,25 @@ create trigger my_table_col_update_trig drop table my_table; -- +-- Verify that transition tables can't be used in, eg, a view. +-- + +create table my_table (a int); +create function make_bogus_matview() returns trigger as +$$ begin + create materialized view transition_test_mv as select * from new_table; + return new; +end $$ +language plpgsql; +create trigger make_bogus_matview + after insert on my_table + referencing new table as new_table + for each statement execute function make_bogus_matview(); +insert into my_table values (42); -- error +drop table my_table; +drop function make_bogus_matview(); + +-- -- Test firing of triggers with transition tables by foreign key cascades -- |