On 2017-Aug-02, Tom Lane wrote: > I think Peter's got the error and the detail backwards. It should be > more like > > ERROR: "someview" cannot have constraints > DETAIL: "someview" is a view. > > If we do it like that, we need one ERROR message per error reason, > and one DETAIL per relkind, which should be manageable.
I support this idea. Here's a proof-of-concept patch that corresponds to one of the cases that Ashutosh was on about (specifically, the one that uses the RELKIND_CAN_HAVE_STORAGE macro I just added). If there are no objections to this approach, I'm going to complete it along these lines. I put the new function at the bottom of heapam.c but I think it probably needs a better place. BTW are there other opinions on the RELKIND_HAS_STORAGE vs. RELKIND_CAN_HAVE_STORAGE debate? I'm inclined to change it to the former. -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
commit 399a6b2fdaffb7b5fb843af77bd4b046cfcce102[m Author: Alvaro Herrera <alvhe...@alvh.no-ip.org> AuthorDate: Wed Dec 19 14:33:07 2018 -0300 CommitDate: Wed Dec 19 15:07:15 2018 -0300 unsuitable relkind diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index db396c8c4b..1f9eeac62b 100644 --- a/contrib/pgstattuple/pgstatindex.c +++ b/contrib/pgstattuple/pgstatindex.c @@ -757,13 +757,11 @@ GetHashPageStats(Page page, HashIndexStat *stats) 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) + if (!RELKIND_CAN_HAVE_STORAGE(rel->rd_rel->relkind)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table, index, materialized view, sequence, or TOAST table", - RelationGetRelationName(rel)))); + errmsg("cannot compute relpages of \"%s\"", + RelationGetRelationName(rel)), + errdetail_unsuitable_relkind(rel->rd_rel->relkind, + RelationGetRelationName(rel)))); } diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 9650145642..fa2c99b367 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -9460,3 +9460,48 @@ heap_mask(char *pagedata, BlockNumber blkno) } } } + +/* + * Add an errdetail to the current error message indicating what the relkind of + * the relation is. This is useful when an operation is being attempted on a + * relation that cannot accept it. + */ +int +errdetail_unsuitable_relkind(char relkind, char *relname) +{ + switch (relkind) + { + case RELKIND_RELATION: + errdetail("%s is a plain table.", relname); + break; + case RELKIND_INDEX: + errdetail("%s is an index.", relname); + break; + case RELKIND_SEQUENCE: + errdetail("%s is a sequence.", relname); + break; + case RELKIND_TOASTVALUE: + errdetail("%s is a TOAST table.", relname); + break; + case RELKIND_VIEW: + errdetail("%s is a view.", relname); + break; + case RELKIND_MATVIEW: + errdetail("%s is a materialized view.", relname); + break; + case RELKIND_COMPOSITE_TYPE: + errdetail("%s is a composite type.", relname); + break; + case RELKIND_FOREIGN_TABLE: + errdetail("%s is a foreign table.", relname); + break; + case RELKIND_PARTITIONED_TABLE: + errdetail("%s is a partitioned table.", relname); + break; + case RELKIND_PARTITIONED_INDEX: + errdetail("%s is a partitioned index.", relname); + break; + } + + return 0; +} diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 64cfdbd2f0..c1679ea2f9 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -184,6 +184,8 @@ extern void simple_heap_update(Relation relation, ItemPointer otid, extern void heap_sync(Relation relation); extern void heap_update_snapshot(HeapScanDesc scan, Snapshot snapshot); +extern int errdetail_unsuitable_relkind(char relkind, char *relname); + /* in heap/pruneheap.c */ extern void heap_page_prune_opt(Relation relation, Buffer buffer); extern int heap_page_prune(Relation relation, Buffer buffer,