Commit 66abc260 authored by Robert Haas's avatar Robert Haas

Add a new reloption, user_catalog_table.

When this reloption is set and wal_level=logical is configured,
we'll record the CIDs stamped by inserts, updates, and deletes to
the table just as we would for an actual catalog table.  This will
allow logical decoding to use historical MVCC snapshots to access
such tables just as they access ordinary catalog tables.

Replication solutions built around the logical decoding machinery
will likely need to set this operation for their configuration
tables; it might also be needed by extensions which perform table
access in their output functions.

Andres Freund, reviewed by myself and others.
parent e55704d8
...@@ -61,6 +61,14 @@ static relopt_bool boolRelOpts[] = ...@@ -61,6 +61,14 @@ static relopt_bool boolRelOpts[] =
}, },
true 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", "fastupdate",
...@@ -1166,6 +1174,8 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) ...@@ -1166,6 +1174,8 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
offsetof(StdRdOptions, security_barrier)}, offsetof(StdRdOptions, security_barrier)},
{"check_option", RELOPT_TYPE_STRING, {"check_option", RELOPT_TYPE_STRING,
offsetof(StdRdOptions, check_option_offset)}, offsetof(StdRdOptions, check_option_offset)},
{"user_catalog_table", RELOPT_TYPE_BOOL,
offsetof(StdRdOptions, user_catalog_table)}
}; };
options = parseRelOptions(reloptions, validate, kind, &numoptions); options = parseRelOptions(reloptions, validate, kind, &numoptions);
......
...@@ -3532,6 +3532,12 @@ ATRewriteTables(List **wqueue, LOCKMODE lockmode) ...@@ -3532,6 +3532,12 @@ ATRewriteTables(List **wqueue, LOCKMODE lockmode)
errmsg("cannot rewrite system relation \"%s\"", errmsg("cannot rewrite system relation \"%s\"",
RelationGetRelationName(OldHeap)))); 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 * Don't allow rewrite on temp tables of other backends ... their
* local buffer manager is not going to cope. * local buffer manager is not going to cope.
......
...@@ -217,6 +217,7 @@ typedef struct StdRdOptions ...@@ -217,6 +217,7 @@ typedef struct StdRdOptions
AutoVacOpts autovacuum; /* autovacuum-related options */ AutoVacOpts autovacuum; /* autovacuum-related options */
bool security_barrier; /* for views */ bool security_barrier; /* for views */
int check_option_offset; /* for views */ int check_option_offset; /* for views */
bool user_catalog_table; /* use as an additional catalog relation */
} StdRdOptions; } StdRdOptions;
#define HEAP_MIN_FILLFACTOR 10 #define HEAP_MIN_FILLFACTOR 10
...@@ -285,6 +286,15 @@ typedef struct StdRdOptions ...@@ -285,6 +286,15 @@ typedef struct StdRdOptions
((StdRdOptions *) (relation)->rd_options)->check_option_offset, \ ((StdRdOptions *) (relation)->rd_options)->check_option_offset, \
"cascaded") == 0 : false) "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 * RelationIsValid
* True iff relation descriptor is valid. * True iff relation descriptor is valid.
...@@ -462,7 +472,7 @@ typedef struct StdRdOptions ...@@ -462,7 +472,7 @@ typedef struct StdRdOptions
#define RelationIsAccessibleInLogicalDecoding(relation) \ #define RelationIsAccessibleInLogicalDecoding(relation) \
(XLogLogicalInfoActive() && \ (XLogLogicalInfoActive() && \
RelationNeedsWAL(relation) && \ RelationNeedsWAL(relation) && \
IsCatalogRelation(relation)) (IsCatalogRelation(relation) || RelationIsUsedAsCatalogTable(relation)))
/* /*
* RelationIsLogicallyLogged * RelationIsLogicallyLogged
...@@ -471,7 +481,9 @@ typedef struct StdRdOptions ...@@ -471,7 +481,9 @@ typedef struct StdRdOptions
* *
* We don't log information for unlogged tables (since they don't WAL log * 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 * 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) \ #define RelationIsLogicallyLogged(relation) \
(XLogLogicalInfoActive() && \ (XLogLogicalInfoActive() && \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment