mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Improve error messages about mismatching relkind
Most error messages about a relkind that was not supported or appropriate for the command was of the pattern "relation \"%s\" is not a table, foreign table, or materialized view" This style can become verbose and tedious to maintain. Moreover, it's not very helpful: If I'm trying to create a comment on a TOAST table, which is not supported, then the information that I could have created a comment on a materialized view is pointless. Instead, write the primary error message shorter and saying more directly that what was attempted is not possible. Then, in the detail message, explain that the operation is not supported for the relkind the object was. To simplify that, add a new function errdetail_relkind_not_supported() that does this. In passing, make use of RELKIND_HAS_STORAGE() where appropriate, instead of listing out the relkinds individually. Reviewed-by: Michael Paquier <michael@paquier.xyz> Reviewed-by: Alvaro Herrera <alvherre@alvh.no-ip.org> Discussion: https://www.postgresql.org/message-id/flat/dc35a398-37d0-75ce-07ea-1dd71d98f8ec@2ndquadrant.com
This commit is contained in:
@ -139,7 +139,8 @@ CREATE TABLE test_partitioned (a int, b text default repeat('x', 5000))
|
||||
SELECT * FROM verify_heapam('test_partitioned',
|
||||
startblock := NULL,
|
||||
endblock := NULL);
|
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table
|
||||
ERROR: cannot check relation "test_partitioned"
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
-- Check that valid options are not rejected nor corruption reported
|
||||
-- for an empty partition table (the child one)
|
||||
CREATE TABLE test_partition partition OF test_partitioned FOR VALUES IN (1);
|
||||
@ -165,19 +166,22 @@ CREATE INDEX test_index ON test_partition (a);
|
||||
SELECT * FROM verify_heapam('test_index',
|
||||
startblock := NULL,
|
||||
endblock := NULL);
|
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table
|
||||
ERROR: cannot check relation "test_index"
|
||||
DETAIL: This operation is not supported for indexes.
|
||||
-- Check that views are rejected
|
||||
CREATE VIEW test_view AS SELECT 1;
|
||||
SELECT * FROM verify_heapam('test_view',
|
||||
startblock := NULL,
|
||||
endblock := NULL);
|
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table
|
||||
ERROR: cannot check relation "test_view"
|
||||
DETAIL: This operation is not supported for views.
|
||||
-- Check that sequences are rejected
|
||||
CREATE SEQUENCE test_sequence;
|
||||
SELECT * FROM verify_heapam('test_sequence',
|
||||
startblock := NULL,
|
||||
endblock := NULL);
|
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table
|
||||
ERROR: cannot check relation "test_sequence"
|
||||
DETAIL: This operation is not supported for sequences.
|
||||
-- Check that foreign tables are rejected
|
||||
CREATE FOREIGN DATA WRAPPER dummy;
|
||||
CREATE SERVER dummy_server FOREIGN DATA WRAPPER dummy;
|
||||
@ -185,7 +189,8 @@ CREATE FOREIGN TABLE test_foreign_table () SERVER dummy_server;
|
||||
SELECT * FROM verify_heapam('test_foreign_table',
|
||||
startblock := NULL,
|
||||
endblock := NULL);
|
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table
|
||||
ERROR: cannot check relation "test_foreign_table"
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
-- cleanup
|
||||
DROP TABLE heaptest;
|
||||
DROP TABLE test_partition;
|
||||
|
@ -147,7 +147,6 @@ typedef struct HeapCheckContext
|
||||
} HeapCheckContext;
|
||||
|
||||
/* Internal implementation */
|
||||
static void sanity_check_relation(Relation rel);
|
||||
static void check_tuple(HeapCheckContext *ctx);
|
||||
static void check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
|
||||
ToastedAttribute *ta, int32 *expected_chunk_seq,
|
||||
@ -300,7 +299,23 @@ verify_heapam(PG_FUNCTION_ARGS)
|
||||
|
||||
/* Open relation, check relkind and access method */
|
||||
ctx.rel = relation_open(relid, AccessShareLock);
|
||||
sanity_check_relation(ctx.rel);
|
||||
|
||||
/*
|
||||
* Check that a relation's relkind and access method are both supported.
|
||||
*/
|
||||
if (ctx.rel->rd_rel->relkind != RELKIND_RELATION &&
|
||||
ctx.rel->rd_rel->relkind != RELKIND_MATVIEW &&
|
||||
ctx.rel->rd_rel->relkind != RELKIND_TOASTVALUE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot check relation \"%s\"",
|
||||
RelationGetRelationName(ctx.rel)),
|
||||
errdetail_relkind_not_supported(ctx.rel->rd_rel->relkind)));
|
||||
|
||||
if (ctx.rel->rd_rel->relam != HEAP_TABLE_AM_OID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("only heap AM is supported")));
|
||||
|
||||
/* Early exit if the relation is empty */
|
||||
nblocks = RelationGetNumberOfBlocks(ctx.rel);
|
||||
@ -523,25 +538,6 @@ verify_heapam(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that a relation's relkind and access method are both supported.
|
||||
*/
|
||||
static void
|
||||
sanity_check_relation(Relation rel)
|
||||
{
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION &&
|
||||
rel->rd_rel->relkind != RELKIND_MATVIEW &&
|
||||
rel->rd_rel->relkind != RELKIND_TOASTVALUE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is not a table, materialized view, or TOAST table",
|
||||
RelationGetRelationName(rel))));
|
||||
if (rel->rd_rel->relam != HEAP_TABLE_AM_OID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("only heap AM is supported")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Shared internal implementation for report_corruption and
|
||||
* report_toast_corruption.
|
||||
|
@ -180,9 +180,11 @@ DROP TABLE test1;
|
||||
create table test_partitioned (a int) partition by range (a);
|
||||
create index test_partitioned_index on test_partitioned (a);
|
||||
select get_raw_page('test_partitioned', 0); -- error about partitioned table
|
||||
ERROR: cannot get raw page from partitioned table "test_partitioned"
|
||||
ERROR: cannot get raw page from relation "test_partitioned"
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
select get_raw_page('test_partitioned_index', 0); -- error about partitioned index
|
||||
ERROR: cannot get raw page from partitioned index "test_partitioned_index"
|
||||
ERROR: cannot get raw page from relation "test_partitioned_index"
|
||||
DETAIL: This operation is not supported for partitioned indexes.
|
||||
-- a regular table which is a member of a partition set should work though
|
||||
create table test_part1 partition of test_partitioned for values from ( 1 ) to (100);
|
||||
select get_raw_page('test_part1', 0); -- get farther and error about empty table
|
||||
|
@ -155,32 +155,12 @@ get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno)
|
||||
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
||||
rel = relation_openrv(relrv, AccessShareLock);
|
||||
|
||||
/* Check that this relation has storage */
|
||||
if (rel->rd_rel->relkind == RELKIND_VIEW)
|
||||
if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot get raw page from view \"%s\"",
|
||||
RelationGetRelationName(rel))));
|
||||
if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot get raw page from composite type \"%s\"",
|
||||
RelationGetRelationName(rel))));
|
||||
if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot get raw page from foreign table \"%s\"",
|
||||
RelationGetRelationName(rel))));
|
||||
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot get raw page from partitioned table \"%s\"",
|
||||
RelationGetRelationName(rel))));
|
||||
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot get raw page from partitioned index \"%s\"",
|
||||
RelationGetRelationName(rel))));
|
||||
errmsg("cannot get raw page from relation \"%s\"",
|
||||
RelationGetRelationName(rel)),
|
||||
errdetail_relkind_not_supported(rel->rd_rel->relkind)));
|
||||
|
||||
/*
|
||||
* Reject attempts to read non-local temporary relations; we would be
|
||||
|
@ -170,9 +170,11 @@ rollback;
|
||||
-- check that it fails on an unsupported relkind
|
||||
create view vw as select 1;
|
||||
select heap_force_kill('vw'::regclass, ARRAY['(0, 1)']::tid[]);
|
||||
ERROR: "vw" is not a table, materialized view, or TOAST table
|
||||
ERROR: cannot operate on relation "vw"
|
||||
DETAIL: This operation is not supported for views.
|
||||
select heap_force_freeze('vw'::regclass, ARRAY['(0, 1)']::tid[]);
|
||||
ERROR: "vw" is not a table, materialized view, or TOAST table
|
||||
ERROR: cannot operate on relation "vw"
|
||||
DETAIL: This operation is not supported for views.
|
||||
-- cleanup.
|
||||
drop view vw;
|
||||
drop extension pg_surgery;
|
||||
|
@ -37,7 +37,6 @@ static int32 tidcmp(const void *a, const void *b);
|
||||
static Datum heap_force_common(FunctionCallInfo fcinfo,
|
||||
HeapTupleForceOption heap_force_opt);
|
||||
static void sanity_check_tid_array(ArrayType *ta, int *ntids);
|
||||
static void sanity_check_relation(Relation rel);
|
||||
static BlockNumber find_tids_one_page(ItemPointer tids, int ntids,
|
||||
OffsetNumber *next_start_ptr);
|
||||
|
||||
@ -101,8 +100,28 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt)
|
||||
|
||||
rel = relation_open(relid, RowExclusiveLock);
|
||||
|
||||
/* Check target relation. */
|
||||
sanity_check_relation(rel);
|
||||
/*
|
||||
* Check target relation.
|
||||
*/
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION &&
|
||||
rel->rd_rel->relkind != RELKIND_MATVIEW &&
|
||||
rel->rd_rel->relkind != RELKIND_TOASTVALUE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot operate on relation \"%s\"",
|
||||
RelationGetRelationName(rel)),
|
||||
errdetail_relkind_not_supported(rel->rd_rel->relkind)));
|
||||
|
||||
if (rel->rd_rel->relam != HEAP_TABLE_AM_OID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("only heap AM is supported")));
|
||||
|
||||
/* Must be owner of the table or superuser. */
|
||||
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER,
|
||||
get_relkind_objtype(rel->rd_rel->relkind),
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
tids = ((ItemPointer) ARR_DATA_PTR(ta));
|
||||
|
||||
@ -363,35 +382,6 @@ sanity_check_tid_array(ArrayType *ta, int *ntids)
|
||||
*ntids = ArrayGetNItems(ARR_NDIM(ta), ARR_DIMS(ta));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* sanity_check_relation()
|
||||
*
|
||||
* Perform sanity checks on the given relation.
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
sanity_check_relation(Relation rel)
|
||||
{
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION &&
|
||||
rel->rd_rel->relkind != RELKIND_MATVIEW &&
|
||||
rel->rd_rel->relkind != RELKIND_TOASTVALUE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is not a table, materialized view, or TOAST table",
|
||||
RelationGetRelationName(rel))));
|
||||
|
||||
if (rel->rd_rel->relam != HEAP_TABLE_AM_OID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("only heap AM is supported")));
|
||||
|
||||
/* Must be owner of the table or superuser. */
|
||||
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER,
|
||||
get_relkind_objtype(rel->rd_rel->relkind),
|
||||
RelationGetRelationName(rel));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* find_tids_one_page()
|
||||
*
|
||||
|
@ -41,66 +41,91 @@ ROLLBACK;
|
||||
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
|
||||
ERROR: relation "test_partitioned" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
select pg_visibility_map('test_partitioned');
|
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_partitioned" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
select pg_visibility_map_summary('test_partitioned');
|
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_partitioned" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
select pg_check_frozen('test_partitioned');
|
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_partitioned" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
select pg_truncate_visibility_map('test_partitioned');
|
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_partitioned" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
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
|
||||
ERROR: relation "test_index" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for indexes.
|
||||
select pg_visibility_map('test_index');
|
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_index" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for indexes.
|
||||
select pg_visibility_map_summary('test_index');
|
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_index" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for indexes.
|
||||
select pg_check_frozen('test_index');
|
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_index" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for indexes.
|
||||
select pg_truncate_visibility_map('test_index');
|
||||
ERROR: "test_index" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_index" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for indexes.
|
||||
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
|
||||
ERROR: relation "test_view" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for views.
|
||||
select pg_visibility_map('test_view');
|
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_view" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for views.
|
||||
select pg_visibility_map_summary('test_view');
|
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_view" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for views.
|
||||
select pg_check_frozen('test_view');
|
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_view" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for views.
|
||||
select pg_truncate_visibility_map('test_view');
|
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_view" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for views.
|
||||
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
|
||||
ERROR: relation "test_sequence" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for sequences.
|
||||
select pg_visibility_map('test_sequence');
|
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_sequence" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for sequences.
|
||||
select pg_visibility_map_summary('test_sequence');
|
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_sequence" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for sequences.
|
||||
select pg_check_frozen('test_sequence');
|
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_sequence" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for sequences.
|
||||
select pg_truncate_visibility_map('test_sequence');
|
||||
ERROR: "test_sequence" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_sequence" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for sequences.
|
||||
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
|
||||
ERROR: relation "test_foreign_table" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
select pg_visibility_map('test_foreign_table');
|
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_foreign_table" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
select pg_visibility_map_summary('test_foreign_table');
|
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_foreign_table" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
select pg_check_frozen('test_foreign_table');
|
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_foreign_table" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
select pg_truncate_visibility_map('test_foreign_table');
|
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_foreign_table" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
-- check some of the allowed relkinds
|
||||
create table regular_table (a int, b text);
|
||||
alter table regular_table alter column b set storage external;
|
||||
|
@ -781,6 +781,7 @@ check_relation_relkind(Relation rel)
|
||||
rel->rd_rel->relkind != RELKIND_TOASTVALUE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is not a table, materialized view, or TOAST table",
|
||||
RelationGetRelationName(rel))));
|
||||
errmsg("relation \"%s\" is of wrong relation kind",
|
||||
RelationGetRelationName(rel)),
|
||||
errdetail_relkind_not_supported(rel->rd_rel->relkind)));
|
||||
}
|
||||
|
@ -155,13 +155,17 @@ create table test_partitioned (a int) partition by range (a);
|
||||
create index test_partitioned_index on test_partitioned(a);
|
||||
-- these should all fail
|
||||
select pgstattuple('test_partitioned');
|
||||
ERROR: "test_partitioned" (partitioned table) is not supported
|
||||
ERROR: cannot get tuple-level statistics for relation "test_partitioned"
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
select pgstattuple('test_partitioned_index');
|
||||
ERROR: "test_partitioned_index" (partitioned index) is not supported
|
||||
ERROR: cannot get tuple-level statistics for relation "test_partitioned_index"
|
||||
DETAIL: This operation is not supported for partitioned indexes.
|
||||
select pgstattuple_approx('test_partitioned');
|
||||
ERROR: "test_partitioned" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_partitioned" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
select pg_relpages('test_partitioned');
|
||||
ERROR: "test_partitioned" is not a table, index, materialized view, sequence, or TOAST table
|
||||
ERROR: cannot get page count of relation "test_partitioned"
|
||||
DETAIL: This operation is not supported for partitioned tables.
|
||||
select pgstatindex('test_partitioned');
|
||||
ERROR: relation "test_partitioned" is not a btree index
|
||||
select pgstatginindex('test_partitioned');
|
||||
@ -171,11 +175,14 @@ ERROR: "test_partitioned" is not an index
|
||||
create view test_view as select 1;
|
||||
-- these should all fail
|
||||
select pgstattuple('test_view');
|
||||
ERROR: "test_view" (view) is not supported
|
||||
ERROR: cannot get tuple-level statistics for relation "test_view"
|
||||
DETAIL: This operation is not supported for views.
|
||||
select pgstattuple_approx('test_view');
|
||||
ERROR: "test_view" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_view" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for views.
|
||||
select pg_relpages('test_view');
|
||||
ERROR: "test_view" is not a table, index, materialized view, sequence, or TOAST table
|
||||
ERROR: cannot get page count of relation "test_view"
|
||||
DETAIL: This operation is not supported for views.
|
||||
select pgstatindex('test_view');
|
||||
ERROR: relation "test_view" is not a btree index
|
||||
select pgstatginindex('test_view');
|
||||
@ -187,11 +194,14 @@ create server dummy_server foreign data wrapper dummy;
|
||||
create foreign table test_foreign_table () server dummy_server;
|
||||
-- these should all fail
|
||||
select pgstattuple('test_foreign_table');
|
||||
ERROR: "test_foreign_table" (foreign table) is not supported
|
||||
ERROR: cannot get tuple-level statistics for relation "test_foreign_table"
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
select pgstattuple_approx('test_foreign_table');
|
||||
ERROR: "test_foreign_table" is not a table, materialized view, or TOAST table
|
||||
ERROR: relation "test_foreign_table" is of wrong relation kind
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
select pg_relpages('test_foreign_table');
|
||||
ERROR: "test_foreign_table" is not a table, index, materialized view, sequence, or TOAST table
|
||||
ERROR: cannot get page count of relation "test_foreign_table"
|
||||
DETAIL: This operation is not supported for foreign tables.
|
||||
select pgstatindex('test_foreign_table');
|
||||
ERROR: relation "test_foreign_table" is not a btree index
|
||||
select pgstatginindex('test_foreign_table');
|
||||
|
@ -289,8 +289,9 @@ pgstattuple_approx_internal(Oid relid, FunctionCallInfo fcinfo)
|
||||
rel->rd_rel->relkind == RELKIND_TOASTVALUE))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("\"%s\" is not a table, materialized view, or TOAST table",
|
||||
RelationGetRelationName(rel))));
|
||||
errmsg("relation \"%s\" is of wrong relation kind",
|
||||
RelationGetRelationName(rel)),
|
||||
errdetail_relkind_not_supported(rel->rd_rel->relkind)));
|
||||
|
||||
if (rel->rd_rel->relam != HEAP_TABLE_AM_OID)
|
||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
|
@ -128,8 +128,8 @@ typedef struct HashIndexStat
|
||||
} HashIndexStat;
|
||||
|
||||
static Datum pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo);
|
||||
static int64 pg_relpages_impl(Relation rel);
|
||||
static void GetHashPageStats(Page page, HashIndexStat *stats);
|
||||
static void check_relation_relkind(Relation rel);
|
||||
|
||||
/* ------------------------------------------------------
|
||||
* pgstatindex()
|
||||
@ -383,7 +383,6 @@ Datum
|
||||
pg_relpages(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *relname = PG_GETARG_TEXT_PP(0);
|
||||
int64 relpages;
|
||||
Relation rel;
|
||||
RangeVar *relrv;
|
||||
|
||||
@ -395,16 +394,7 @@ pg_relpages(PG_FUNCTION_ARGS)
|
||||
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
||||
rel = relation_openrv(relrv, AccessShareLock);
|
||||
|
||||
/* only some relkinds have storage */
|
||||
check_relation_relkind(rel);
|
||||
|
||||
/* note: this will work OK on non-local temp tables */
|
||||
|
||||
relpages = RelationGetNumberOfBlocks(rel);
|
||||
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
PG_RETURN_INT64(relpages);
|
||||
PG_RETURN_INT64(pg_relpages_impl(rel));
|
||||
}
|
||||
|
||||
/* No need for superuser checks in v1.5, see above */
|
||||
@ -412,23 +402,13 @@ Datum
|
||||
pg_relpages_v1_5(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *relname = PG_GETARG_TEXT_PP(0);
|
||||
int64 relpages;
|
||||
Relation rel;
|
||||
RangeVar *relrv;
|
||||
|
||||
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
||||
rel = relation_openrv(relrv, AccessShareLock);
|
||||
|
||||
/* only some relkinds have storage */
|
||||
check_relation_relkind(rel);
|
||||
|
||||
/* note: this will work OK on non-local temp tables */
|
||||
|
||||
relpages = RelationGetNumberOfBlocks(rel);
|
||||
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
PG_RETURN_INT64(relpages);
|
||||
PG_RETURN_INT64(pg_relpages_impl(rel));
|
||||
}
|
||||
|
||||
/* Must keep superuser() check, see above. */
|
||||
@ -436,7 +416,6 @@ Datum
|
||||
pg_relpagesbyid(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid relid = PG_GETARG_OID(0);
|
||||
int64 relpages;
|
||||
Relation rel;
|
||||
|
||||
if (!superuser())
|
||||
@ -446,16 +425,7 @@ pg_relpagesbyid(PG_FUNCTION_ARGS)
|
||||
|
||||
rel = relation_open(relid, AccessShareLock);
|
||||
|
||||
/* only some relkinds have storage */
|
||||
check_relation_relkind(rel);
|
||||
|
||||
/* note: this will work OK on non-local temp tables */
|
||||
|
||||
relpages = RelationGetNumberOfBlocks(rel);
|
||||
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
PG_RETURN_INT64(relpages);
|
||||
PG_RETURN_INT64(pg_relpages_impl(rel));
|
||||
}
|
||||
|
||||
/* No need for superuser checks in v1.5, see above */
|
||||
@ -463,13 +433,24 @@ Datum
|
||||
pg_relpagesbyid_v1_5(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid relid = PG_GETARG_OID(0);
|
||||
int64 relpages;
|
||||
Relation rel;
|
||||
|
||||
rel = relation_open(relid, AccessShareLock);
|
||||
|
||||
/* only some relkinds have storage */
|
||||
check_relation_relkind(rel);
|
||||
PG_RETURN_INT64(pg_relpages_impl(rel));
|
||||
}
|
||||
|
||||
static int64
|
||||
pg_relpages_impl(Relation rel)
|
||||
{
|
||||
int64 relpages;
|
||||
|
||||
if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot get page count of relation \"%s\"",
|
||||
RelationGetRelationName(rel)),
|
||||
errdetail_relkind_not_supported(rel->rd_rel->relkind)));
|
||||
|
||||
/* note: this will work OK on non-local temp tables */
|
||||
|
||||
@ -477,7 +458,7 @@ pg_relpagesbyid_v1_5(PG_FUNCTION_ARGS)
|
||||
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
PG_RETURN_INT64(relpages);
|
||||
return relpages;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------
|
||||
@ -754,21 +735,3 @@ GetHashPageStats(Page page, HashIndexStat *stats)
|
||||
}
|
||||
stats->free_space += PageGetExactFreeSpace(page);
|
||||
}
|
||||
|
||||
/*
|
||||
* check_relation_relkind - convenience routine to check that relation
|
||||
* is of the relkind supported by the callers
|
||||
*/
|
||||
static void
|
||||
check_relation_relkind(Relation rel)
|
||||
{
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION &&
|
||||
rel->rd_rel->relkind != RELKIND_INDEX &&
|
||||
rel->rd_rel->relkind != RELKIND_MATVIEW &&
|
||||
rel->rd_rel->relkind != RELKIND_SEQUENCE &&
|
||||
rel->rd_rel->relkind != RELKIND_TOASTVALUE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is not a table, index, materialized view, sequence, or TOAST table",
|
||||
RelationGetRelationName(rel))));
|
||||
}
|
||||
|
@ -284,31 +284,20 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
|
||||
err = "unknown index";
|
||||
break;
|
||||
}
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("index \"%s\" (%s) is not supported",
|
||||
RelationGetRelationName(rel), err)));
|
||||
break;
|
||||
case RELKIND_VIEW:
|
||||
err = "view";
|
||||
break;
|
||||
case RELKIND_COMPOSITE_TYPE:
|
||||
err = "composite type";
|
||||
break;
|
||||
case RELKIND_FOREIGN_TABLE:
|
||||
err = "foreign table";
|
||||
break;
|
||||
case RELKIND_PARTITIONED_TABLE:
|
||||
err = "partitioned table";
|
||||
break;
|
||||
case RELKIND_PARTITIONED_INDEX:
|
||||
err = "partitioned index";
|
||||
break;
|
||||
|
||||
default:
|
||||
err = "unknown";
|
||||
break;
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot get tuple-level statistics for relation \"%s\"",
|
||||
RelationGetRelationName(rel)),
|
||||
errdetail_relkind_not_supported(rel->rd_rel->relkind)));
|
||||
}
|
||||
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("\"%s\" (%s) is not supported",
|
||||
RelationGetRelationName(rel), err)));
|
||||
return 0; /* should not happen */
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user