I think pg_class is a reasonable place to put more generic relkind lists
alongside a matching error message for each, rather than specialized
"does this relkind have storage" macros. What about something like a
struct list in pg_class.h,
{ {relkinds_r_i_T,{ 'r', 'i', 'T' },gettext_noop("relation %s is not a table, index or toast table") }, ...
}
and then in the .c checks you do something like
relkinds = relkind_r_i_T; if (rel_doesnt_match(rel, relkinds))ereport(ERROR, (errcode(...),
errmsg(relkinds_get_message(relkinds)));
then, in order to update the set of relkinds that some particular
operation works with, you just need to change the "relkinds" variable,
and the message is automatically up to date (you may need to add a new
entry, if there isn't one for the set you want, but the number of
permutations needed shouldn't grow too large). This doesn't create a
problem for translators because you're not constructing an error
message, and it doesn't pollute pg_class.h with things that don't really
belong there.
One possible objection is that rel_doesnt_match() in the above
formulation is slow, because it has to scan the entire list. Maybe this
is not a problem because the list isn't large anyway, or maybe there's
some better formulation -- for example, we could assign a distinct bit
to each relkind, and create bitmasks for each set; then figuring out
whether there's a match or not is just a matter of bit-anding.
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services