mirror of https://github.com/postgres/postgres
The contrib extensions pageinspect, pg_visibility and pgstattuple only work against regular relations which have storage. They don't work against foreign tables, partitioned (parent) tables, views, et al. Add checks to the user-callable functions to return a useful error message to the user if they mistakenly pass an invalid relation to a function which doesn't accept that kind of relation. In passing, improve some of the existing checks to use ereport() instead of elog(), add a function to consolidate common checks where appropriate, and add some regression tests. Author: Amit Langote, with various changes by me Reviewed by: Michael Paquier and Corey Huinker Discussion: https://postgr.es/m/ab91fd9d-4751-ee77-c87b-4dd704c1e59c@lab.ntt.co.jppull/17/merge
parent
b54aad8e34
commit
c08d82f38e
@ -0,0 +1,4 @@ |
||||
# Generated subdirectories |
||||
/log/ |
||||
/results/ |
||||
/tmp_check/ |
@ -0,0 +1,142 @@ |
||||
CREATE EXTENSION pg_visibility; |
||||
-- |
||||
-- check that using the module's functions with unsupported relations will fail |
||||
-- |
||||
-- partitioned tables (the parent ones) don't have visibility maps |
||||
create table test_partitioned (a int) partition by list (a); |
||||
-- these should all fail |
||||
select pg_visibility('test_partitioned', 0); |
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map('test_partitioned'); |
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map_summary('test_partitioned'); |
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table |
||||
select pg_check_frozen('test_partitioned'); |
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table |
||||
select pg_truncate_visibility_map('test_partitioned'); |
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table |
||||
create table test_partition partition of test_partitioned for values in (1); |
||||
create index test_index on test_partition (a); |
||||
-- indexes do not, so these all fail |
||||
select pg_visibility('test_index', 0); |
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map('test_index'); |
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map_summary('test_index'); |
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table |
||||
select pg_check_frozen('test_index'); |
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table |
||||
select pg_truncate_visibility_map('test_index'); |
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table |
||||
create view test_view as select 1; |
||||
-- views do not have VMs, so these all fail |
||||
select pg_visibility('test_view', 0); |
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map('test_view'); |
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map_summary('test_view'); |
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table |
||||
select pg_check_frozen('test_view'); |
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table |
||||
select pg_truncate_visibility_map('test_view'); |
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table |
||||
create sequence test_sequence; |
||||
-- sequences do not have VMs, so these all fail |
||||
select pg_visibility('test_sequence', 0); |
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map('test_sequence'); |
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map_summary('test_sequence'); |
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table |
||||
select pg_check_frozen('test_sequence'); |
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table |
||||
select pg_truncate_visibility_map('test_sequence'); |
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table |
||||
create foreign data wrapper dummy; |
||||
create server dummy_server foreign data wrapper dummy; |
||||
create foreign table test_foreign_table () server dummy_server; |
||||
-- foreign tables do not have VMs, so these all fail |
||||
select pg_visibility('test_foreign_table', 0); |
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map('test_foreign_table'); |
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table |
||||
select pg_visibility_map_summary('test_foreign_table'); |
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table |
||||
select pg_check_frozen('test_foreign_table'); |
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table |
||||
select pg_truncate_visibility_map('test_foreign_table'); |
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table |
||||
-- check some of the allowed relkinds |
||||
create table regular_table (a int); |
||||
insert into regular_table values (1), (2); |
||||
vacuum regular_table; |
||||
select count(*) > 0 from pg_visibility('regular_table'); |
||||
?column? |
||||
---------- |
||||
t |
||||
(1 row) |
||||
|
||||
truncate regular_table; |
||||
select count(*) > 0 from pg_visibility('regular_table'); |
||||
?column? |
||||
---------- |
||||
f |
||||
(1 row) |
||||
|
||||
create materialized view matview_visibility_test as select * from regular_table; |
||||
vacuum matview_visibility_test; |
||||
select count(*) > 0 from pg_visibility('matview_visibility_test'); |
||||
?column? |
||||
---------- |
||||
f |
||||
(1 row) |
||||
|
||||
insert into regular_table values (1), (2); |
||||
refresh materialized view matview_visibility_test; |
||||
select count(*) > 0 from pg_visibility('matview_visibility_test'); |
||||
?column? |
||||
---------- |
||||
t |
||||
(1 row) |
||||
|
||||
-- regular tables which are part of a partition *do* have visibility maps |
||||
insert into test_partition values (1); |
||||
vacuum test_partition; |
||||
select count(*) > 0 from pg_visibility('test_partition', 0); |
||||
?column? |
||||
---------- |
||||
t |
||||
(1 row) |
||||
|
||||
select count(*) > 0 from pg_visibility_map('test_partition'); |
||||
?column? |
||||
---------- |
||||
t |
||||
(1 row) |
||||
|
||||
select count(*) > 0 from pg_visibility_map_summary('test_partition'); |
||||
?column? |
||||
---------- |
||||
t |
||||
(1 row) |
||||
|
||||
select * from pg_check_frozen('test_partition'); -- hopefully none |
||||
t_ctid |
||||
-------- |
||||
(0 rows) |
||||
|
||||
select pg_truncate_visibility_map('test_partition'); |
||||
pg_truncate_visibility_map |
||||
---------------------------- |
||||
|
||||
(1 row) |
||||
|
||||
-- cleanup |
||||
drop table test_partitioned; |
||||
drop view test_view; |
||||
drop sequence test_sequence; |
||||
drop foreign table test_foreign_table; |
||||
drop server dummy_server; |
||||
drop foreign data wrapper dummy; |
||||
drop materialized view matview_visibility_test; |
||||
drop table regular_table; |
@ -0,0 +1,83 @@ |
||||
CREATE EXTENSION pg_visibility; |
||||
|
||||
-- |
||||
-- check that using the module's functions with unsupported relations will fail |
||||
-- |
||||
|
||||
-- partitioned tables (the parent ones) don't have visibility maps |
||||
create table test_partitioned (a int) partition by list (a); |
||||
-- these should all fail |
||||
select pg_visibility('test_partitioned', 0); |
||||
select pg_visibility_map('test_partitioned'); |
||||
select pg_visibility_map_summary('test_partitioned'); |
||||
select pg_check_frozen('test_partitioned'); |
||||
select pg_truncate_visibility_map('test_partitioned'); |
||||
|
||||
create table test_partition partition of test_partitioned for values in (1); |
||||
create index test_index on test_partition (a); |
||||
-- indexes do not, so these all fail |
||||
select pg_visibility('test_index', 0); |
||||
select pg_visibility_map('test_index'); |
||||
select pg_visibility_map_summary('test_index'); |
||||
select pg_check_frozen('test_index'); |
||||
select pg_truncate_visibility_map('test_index'); |
||||
|
||||
create view test_view as select 1; |
||||
-- views do not have VMs, so these all fail |
||||
select pg_visibility('test_view', 0); |
||||
select pg_visibility_map('test_view'); |
||||
select pg_visibility_map_summary('test_view'); |
||||
select pg_check_frozen('test_view'); |
||||
select pg_truncate_visibility_map('test_view'); |
||||
|
||||
create sequence test_sequence; |
||||
-- sequences do not have VMs, so these all fail |
||||
select pg_visibility('test_sequence', 0); |
||||
select pg_visibility_map('test_sequence'); |
||||
select pg_visibility_map_summary('test_sequence'); |
||||
select pg_check_frozen('test_sequence'); |
||||
select pg_truncate_visibility_map('test_sequence'); |
||||
|
||||
create foreign data wrapper dummy; |
||||
create server dummy_server foreign data wrapper dummy; |
||||
create foreign table test_foreign_table () server dummy_server; |
||||
-- foreign tables do not have VMs, so these all fail |
||||
select pg_visibility('test_foreign_table', 0); |
||||
select pg_visibility_map('test_foreign_table'); |
||||
select pg_visibility_map_summary('test_foreign_table'); |
||||
select pg_check_frozen('test_foreign_table'); |
||||
select pg_truncate_visibility_map('test_foreign_table'); |
||||
|
||||
-- check some of the allowed relkinds |
||||
create table regular_table (a int); |
||||
insert into regular_table values (1), (2); |
||||
vacuum regular_table; |
||||
select count(*) > 0 from pg_visibility('regular_table'); |
||||
truncate regular_table; |
||||
select count(*) > 0 from pg_visibility('regular_table'); |
||||
|
||||
create materialized view matview_visibility_test as select * from regular_table; |
||||
vacuum matview_visibility_test; |
||||
select count(*) > 0 from pg_visibility('matview_visibility_test'); |
||||
insert into regular_table values (1), (2); |
||||
refresh materialized view matview_visibility_test; |
||||
select count(*) > 0 from pg_visibility('matview_visibility_test'); |
||||
|
||||
-- regular tables which are part of a partition *do* have visibility maps |
||||
insert into test_partition values (1); |
||||
vacuum test_partition; |
||||
select count(*) > 0 from pg_visibility('test_partition', 0); |
||||
select count(*) > 0 from pg_visibility_map('test_partition'); |
||||
select count(*) > 0 from pg_visibility_map_summary('test_partition'); |
||||
select * from pg_check_frozen('test_partition'); -- hopefully none |
||||
select pg_truncate_visibility_map('test_partition'); |
||||
|
||||
-- cleanup |
||||
drop table test_partitioned; |
||||
drop view test_view; |
||||
drop sequence test_sequence; |
||||
drop foreign table test_foreign_table; |
||||
drop server dummy_server; |
||||
drop foreign data wrapper dummy; |
||||
drop materialized view matview_visibility_test; |
||||
drop table regular_table; |
Loading…
Reference in new issue