1
0
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:
Peter Eisentraut
2021-07-08 09:38:52 +02:00
parent b9734c13f1
commit 2ed532ee8c
32 changed files with 512 additions and 378 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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()
*

View File

@ -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;

View File

@ -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)));
}

View File

@ -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');

View File

@ -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),

View File

@ -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))));
}

View File

@ -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 */
}