diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index b5fd30a4f95933ef414607ca831464065d8cc9d6..31941e99edbd76fb8baf85a6c749fe1194cdb917 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -61,6 +61,14 @@ static relopt_bool boolRelOpts[] = }, true }, + { + { + "user_catalog_table", + "Declare a table as an additional catalog table, e.g. for the purpose of logical replication", + RELOPT_KIND_HEAP + }, + false + }, { { "fastupdate", @@ -1166,6 +1174,8 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) offsetof(StdRdOptions, security_barrier)}, {"check_option", RELOPT_TYPE_STRING, offsetof(StdRdOptions, check_option_offset)}, + {"user_catalog_table", RELOPT_TYPE_BOOL, + offsetof(StdRdOptions, user_catalog_table)} }; options = parseRelOptions(reloptions, validate, kind, &numoptions); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 1d9f29a7b7c18742cc3c2639e20c4ba4bd0763fe..b9cd88d57015416066c7f3db70d9c681708426ff 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3532,6 +3532,12 @@ ATRewriteTables(List **wqueue, LOCKMODE lockmode) errmsg("cannot rewrite system relation \"%s\"", RelationGetRelationName(OldHeap)))); + if (RelationIsUsedAsCatalogTable(OldHeap)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot rewrite table \"%s\" used as a catalog table", + RelationGetRelationName(OldHeap)))); + /* * Don't allow rewrite on temp tables of other backends ... their * local buffer manager is not going to cope. diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index ad878cf1a225b61c7fddb7016337cc09214aa8df..383744b3a0c350860dd054b206c5f652535d83b0 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -217,6 +217,7 @@ typedef struct StdRdOptions AutoVacOpts autovacuum; /* autovacuum-related options */ bool security_barrier; /* for views */ int check_option_offset; /* for views */ + bool user_catalog_table; /* use as an additional catalog relation */ } StdRdOptions; #define HEAP_MIN_FILLFACTOR 10 @@ -285,6 +286,15 @@ typedef struct StdRdOptions ((StdRdOptions *) (relation)->rd_options)->check_option_offset, \ "cascaded") == 0 : false) +/* + * RelationIsUsedAsCatalogTable + * Returns whether the relation should be treated as a catalog table + * from the pov of logical decoding. + */ +#define RelationIsUsedAsCatalogTable(relation) \ + ((relation)->rd_options ? \ + ((StdRdOptions *) (relation)->rd_options)->user_catalog_table : false) + /* * RelationIsValid * True iff relation descriptor is valid. @@ -462,7 +472,7 @@ typedef struct StdRdOptions #define RelationIsAccessibleInLogicalDecoding(relation) \ (XLogLogicalInfoActive() && \ RelationNeedsWAL(relation) && \ - IsCatalogRelation(relation)) + (IsCatalogRelation(relation) || RelationIsUsedAsCatalogTable(relation))) /* * RelationIsLogicallyLogged @@ -471,7 +481,9 @@ typedef struct StdRdOptions * * We don't log information for unlogged tables (since they don't WAL log * anyway) and for system tables (their content is hard to make sense of, and - * it would complicate decoding slightly for little gain). + * it would complicate decoding slightly for little gain). Note that we *do* + * log information for user defined catalog tables since they presumably are + * interesting to the user... */ #define RelationIsLogicallyLogged(relation) \ (XLogLogicalInfoActive() && \