v6-0003-Added-skip-table-option-to-skip-tables-for-all-ta.patch
text/x-patch
Filename: v6-0003-Added-skip-table-option-to-skip-tables-for-all-ta.patch
Type: text/x-patch
Part: 2
Patch
Format: format-patch
Series: patch v6-0003
Subject: Added skip-table option to skip tables for all tables/for schema publication.
| File | + | − |
|---|---|---|
| src/backend/catalog/aclchk.c | 2 | 0 |
| src/backend/catalog/dependency.c | 10 | 1 |
| src/backend/catalog/Makefile | 1 | 1 |
| src/backend/catalog/objectaddress.c | 91 | 7 |
| src/backend/catalog/pg_publication.c | 68 | 34 |
| src/backend/commands/alter.c | 1 | 0 |
| src/backend/commands/event_trigger.c | 4 | 0 |
| src/backend/commands/publicationcmds.c | 88 | 41 |
| src/backend/commands/seclabel.c | 1 | 0 |
| src/backend/commands/tablecmds.c | 1 | 0 |
| src/backend/parser/gram.y | 46 | 7 |
| src/backend/replication/pgoutput/pgoutput.c | 22 | 15 |
| src/backend/utils/cache/syscache.c | 23 | 0 |
| src/bin/pg_dump/common.c | 4 | 1 |
| src/bin/pg_dump/pg_dump.c | 28 | 13 |
| src/bin/pg_dump/pg_dump.h | 2 | 1 |
| src/bin/pg_dump/pg_dump_sort.c | 7 | 0 |
| src/bin/psql/describe.c | 22 | 3 |
| src/bin/psql/tab-complete.c | 9 | 3 |
| src/include/catalog/dependency.h | 1 | 0 |
| src/include/catalog/pg_publication.h | 27 | 0 |
| src/include/catalog/pg_publication_skiprel.h | 48 | 0 |
| src/include/commands/publicationcmds.h | 6 | 4 |
| src/include/nodes/parsenodes.h | 3 | 0 |
| src/include/parser/kwlist.h | 1 | 0 |
| src/include/utils/syscache.h | 2 | 0 |
| src/test/regress/expected/oidjoins.out | 2 | 0 |
| src/test/regress/expected/sanity_check.out | 1 | 0 |
From 423c9e47c0f06716db103b854549a7d7b777bf90 Mon Sep 17 00:00:00 2001
From: vignesh <vignesh21@gmail.com>
Date: Wed, 16 Jun 2021 18:05:27 +0530
Subject: [PATCH v6 3/4] Added skip-table option to skip tables for all
tables/for schema publication.
Added skip-table option to skip tables for all tables/for schema publication.
---
src/backend/catalog/Makefile | 2 +-
src/backend/catalog/aclchk.c | 2 +
src/backend/catalog/dependency.c | 11 +-
src/backend/catalog/objectaddress.c | 98 +++++++++++++-
src/backend/catalog/pg_publication.c | 102 ++++++++++-----
src/backend/commands/alter.c | 1 +
src/backend/commands/event_trigger.c | 4 +
src/backend/commands/publicationcmds.c | 129 +++++++++++++------
src/backend/commands/seclabel.c | 1 +
src/backend/commands/tablecmds.c | 1 +
src/backend/parser/gram.y | 53 +++++++-
src/backend/replication/pgoutput/pgoutput.c | 37 +++---
src/backend/utils/cache/syscache.c | 23 ++++
src/bin/pg_dump/common.c | 5 +-
src/bin/pg_dump/pg_dump.c | 41 ++++--
src/bin/pg_dump/pg_dump.h | 3 +-
src/bin/pg_dump/pg_dump_sort.c | 7 +
src/bin/psql/describe.c | 25 +++-
src/bin/psql/tab-complete.c | 12 +-
src/include/catalog/dependency.h | 1 +
src/include/catalog/pg_publication.h | 27 ++++
src/include/catalog/pg_publication_skiprel.h | 48 +++++++
src/include/commands/publicationcmds.h | 10 +-
src/include/nodes/parsenodes.h | 3 +
src/include/parser/kwlist.h | 1 +
src/include/utils/syscache.h | 2 +
src/test/regress/expected/oidjoins.out | 2 +
src/test/regress/expected/sanity_check.out | 1 +
28 files changed, 521 insertions(+), 131 deletions(-)
create mode 100644 src/include/catalog/pg_publication_skiprel.h
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 30026a967b..1b51cc9545 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -68,7 +68,7 @@ CATALOG_HEADERS := \
pg_default_acl.h pg_init_privs.h pg_seclabel.h pg_shseclabel.h \
pg_collation.h pg_partitioned_table.h pg_range.h pg_transform.h \
pg_sequence.h pg_publication.h pg_publication_rel.h pg_publication_schema.h \
- pg_subscription.h pg_subscription_rel.h
+ pg_publication_skiprel.h pg_subscription.h pg_subscription_rel.h
GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h system_fk_info.h
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 59600fc98d..f5f01c500f 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -3434,6 +3434,7 @@ aclcheck_error(AclResult aclerr, ObjectType objtype,
case OBJECT_DOMCONSTRAINT:
case OBJECT_PUBLICATION_REL:
case OBJECT_PUBLICATION_SCHEMA:
+ case OBJECT_PUBLICATION_SKIP:
case OBJECT_ROLE:
case OBJECT_RULE:
case OBJECT_TABCONSTRAINT:
@@ -3574,6 +3575,7 @@ aclcheck_error(AclResult aclerr, ObjectType objtype,
case OBJECT_DOMCONSTRAINT:
case OBJECT_PUBLICATION_REL:
case OBJECT_PUBLICATION_SCHEMA:
+ case OBJECT_PUBLICATION_SKIP:
case OBJECT_ROLE:
case OBJECT_TRANSFORM:
case OBJECT_TSPARSER:
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index c0a9fb0c7e..de88f1b046 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -50,6 +50,7 @@
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_rel.h"
#include "catalog/pg_publication_schema.h"
+#include "catalog/pg_publication_skiprel.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
@@ -181,6 +182,7 @@ static const Oid object_classes[] = {
PublicationRelationId, /* OCLASS_PUBLICATION */
PublicationRelRelationId, /* OCLASS_PUBLICATION_REL */
PublicationSchemaRelationId, /* OCLASS_PUBLICATION_SCHEMA */
+ PublicationSkipRelationId, /* OCLASS_PUBLICATION_SKIP */
SubscriptionRelationId, /* OCLASS_SUBSCRIPTION */
TransformRelationId /* OCLASS_TRANSFORM */
};
@@ -1469,13 +1471,17 @@ doDeletion(const ObjectAddress *object, int flags)
break;
case OCLASS_PUBLICATION_REL:
- RemovePublicationRelById(object->objectId);
+ RemovePublicationRelById(object->objectId, false);
break;
case OCLASS_PUBLICATION_SCHEMA:
RemovePublicationSchemaById(object->objectId);
break;
+ case OCLASS_PUBLICATION_SKIP:
+ RemovePublicationRelById(object->objectId, true);
+ break;
+
case OCLASS_CAST:
case OCLASS_COLLATION:
case OCLASS_CONVERSION:
@@ -2872,6 +2878,9 @@ getObjectClass(const ObjectAddress *object)
case PublicationSchemaRelationId:
return OCLASS_PUBLICATION_SCHEMA;
+ case PublicationSkipRelationId:
+ return OCLASS_PUBLICATION_SKIP;
+
case SubscriptionRelationId:
return OCLASS_SUBSCRIPTION;
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index cae0b3b7e6..6aebfbbe06 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -50,6 +50,7 @@
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_rel.h"
#include "catalog/pg_publication_schema.h"
+#include "catalog/pg_publication_skiprel.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
@@ -835,6 +836,10 @@ static const struct object_type_map
{
"publication schema", OBJECT_PUBLICATION_SCHEMA
},
+ /* OCLASS_PUBLICATION_SKIPREL */
+ {
+ "publication skiprelation", OBJECT_PUBLICATION_SKIP
+ },
/* OCLASS_SUBSCRIPTION */
{
"subscription", OBJECT_SUBSCRIPTION
@@ -880,7 +885,8 @@ static ObjectAddress get_object_address_usermapping(List *object,
bool missing_ok);
static ObjectAddress get_object_address_publication_rel(List *object,
Relation *relp,
- bool missing_ok);
+ bool missing_ok,
+ bool is_skip);
static ObjectAddress get_object_address_publication_schema(List *object,
bool missing_ok);
@@ -1125,12 +1131,17 @@ get_object_address(ObjectType objtype, Node *object,
case OBJECT_PUBLICATION_REL:
address = get_object_address_publication_rel(castNode(List, object),
&relation,
- missing_ok);
+ missing_ok, false);
break;
case OBJECT_PUBLICATION_SCHEMA:
address = get_object_address_publication_schema(castNode(List, object),
missing_ok);
break;
+ case OBJECT_PUBLICATION_SKIP:
+ address = get_object_address_publication_rel(castNode(List, object),
+ &relation,
+ missing_ok, true);
+ break;
case OBJECT_DEFACL:
address = get_object_address_defacl(castNode(List, object),
missing_ok);
@@ -1900,16 +1911,19 @@ get_object_address_usermapping(List *object, bool missing_ok)
* publication name.
*/
static ObjectAddress
-get_object_address_publication_rel(List *object,
- Relation *relp, bool missing_ok)
+get_object_address_publication_rel(List *object, Relation *relp,
+ bool missing_ok, bool is_skip)
{
ObjectAddress address;
Relation relation;
List *relname;
char *pubname;
Publication *pub;
+ int relid = GET_PUBLICATION_REL_ID(is_skip);
+ int syscacheid = GET_PUBLICATION_MAP(is_skip);
+ int col_oid = GET_PUBLICATION_COL_OBJECTID(is_skip);
- ObjectAddressSet(address, PublicationRelRelationId, InvalidOid);
+ ObjectAddressSet(address, relid, InvalidOid);
relname = linitial(object);
relation = relation_openrv_extended(makeRangeVarFromNameList(relname),
@@ -1930,15 +1944,17 @@ get_object_address_publication_rel(List *object,
/* Find the publication relation mapping in syscache. */
address.objectId =
- GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
+ GetSysCacheOid2(syscacheid, col_oid,
ObjectIdGetDatum(RelationGetRelid(relation)),
ObjectIdGetDatum(pub->oid));
+
if (!OidIsValid(address.objectId))
{
if (!missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
+ errmsg("publication %s \"%s\" in publication \"%s\" does not exist",
+ GET_PUBLICATION_REL_STR(is_skip),
RelationGetRelationName(relation), pubname)));
relation_close(relation, AccessShareLock);
return address;
@@ -2266,6 +2282,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
case OBJECT_USER_MAPPING:
case OBJECT_PUBLICATION_REL:
case OBJECT_PUBLICATION_SCHEMA:
+ case OBJECT_PUBLICATION_SKIP:
case OBJECT_DEFACL:
case OBJECT_TRANSFORM:
if (list_length(args) != 1)
@@ -2361,6 +2378,9 @@ pg_get_object_address(PG_FUNCTION_ARGS)
case OBJECT_PUBLICATION_SCHEMA:
objnode = (Node *) list_make2(linitial(name), linitial(args));
break;
+ case OBJECT_PUBLICATION_SKIP:
+ objnode = (Node *) list_make2(name, linitial(args));
+ break;
case OBJECT_USER_MAPPING:
objnode = (Node *) list_make2(linitial(name), linitial(args));
break;
@@ -4003,6 +4023,37 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok)
break;
}
+ case OCLASS_PUBLICATION_SKIP:
+ {
+ HeapTuple tup;
+ char *pubname;
+ Form_pg_publication_skip psform;
+ StringInfoData rel;
+
+ tup = SearchSysCache1(PUBLICATIONSKIP,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ {
+ if (!missing_ok)
+ elog(ERROR, "cache lookup failed for publication table %u",
+ object->objectId);
+ break;
+ }
+
+ psform = (Form_pg_publication_skip) GETSTRUCT(tup);
+ pubname = get_publication_name(psform->pspubid, false);
+
+ initStringInfo(&rel);
+ getRelationDescription(&rel, psform->psrelid, false);
+
+ /* translator: first %s is, e.g., "table %s" */
+ appendStringInfo(&buffer, _("publication of %s in publication %s"),
+ rel.data, pubname);
+ pfree(rel.data);
+ ReleaseSysCache(tup);
+ break;
+ }
+
case OCLASS_SUBSCRIPTION:
{
char *subname = get_subscription_name(object->objectId,
@@ -4581,6 +4632,10 @@ getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
appendStringInfoString(&buffer, "publication schema");
break;
+ case OCLASS_PUBLICATION_SKIP:
+ appendStringInfoString(&buffer, "publication skiprelation");
+ break;
+
case OCLASS_SUBSCRIPTION:
appendStringInfoString(&buffer, "subscription");
break;
@@ -5858,6 +5913,35 @@ getObjectIdentityParts(const ObjectAddress *object,
break;
}
+ case OCLASS_PUBLICATION_SKIP:
+ {
+ HeapTuple tup;
+ char *pubname;
+ Form_pg_publication_skip psform;
+
+ tup = SearchSysCache1(PUBLICATIONSKIP,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ {
+ if (!missing_ok)
+ elog(ERROR, "cache lookup failed for publication table %u",
+ object->objectId);
+ break;
+ }
+
+ psform = (Form_pg_publication_skip) GETSTRUCT(tup);
+ pubname = get_publication_name(psform->pspubid, false);
+
+ getRelationIdentity(&buffer, psform->psrelid, objname, false);
+ appendStringInfo(&buffer, " in publication %s", pubname);
+
+ if (objargs)
+ *objargs = list_make1(pubname);
+
+ ReleaseSysCache(tup);
+ break;
+ }
+
case OCLASS_SUBSCRIPTION:
{
char *subname;
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index 41243790d6..05df5b43b0 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -32,6 +32,7 @@
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_rel.h"
#include "catalog/pg_publication_schema.h"
+#include "catalog/pg_publication_skiprel.h"
#include "catalog/pg_type.h"
#include "commands/publicationcmds.h"
#include "funcapi.h"
@@ -145,26 +146,29 @@ pg_relation_is_publishable(PG_FUNCTION_ARGS)
*/
ObjectAddress
publication_add_relation(Oid pubid, Relation targetrel,
- bool if_not_exists)
+ bool if_not_exists, bool is_skip)
{
Relation rel;
HeapTuple tup;
- Datum values[Natts_pg_publication_rel];
- bool nulls[Natts_pg_publication_rel];
+ int ncolumns = GET_PUBLICATION_REL_COL_COUNT(is_skip);
+ Datum *values;
+ bool *nulls;
Oid relid = RelationGetRelid(targetrel);
Oid prrelid;
+ int colid;
Publication *pub = GetPublication(pubid);
ObjectAddress myself,
referenced;
- rel = table_open(PublicationRelRelationId, RowExclusiveLock);
+ rel = table_open(GET_PUBLICATION_REL_ID(is_skip), RowExclusiveLock);
/*
* Check for duplicates. Note that this does not really prevent
* duplicates, it's here just to provide nicer error message in common
* case. The real protection is the unique key on the catalog.
*/
- if (SearchSysCacheExists2(PUBLICATIONRELMAP, ObjectIdGetDatum(relid),
+ if (SearchSysCacheExists2(GET_PUBLICATION_MAP(is_skip),
+ ObjectIdGetDatum(relid),
ObjectIdGetDatum(pubid)))
{
table_close(rel, RowExclusiveLock);
@@ -174,23 +178,24 @@ publication_add_relation(Oid pubid, Relation targetrel,
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("relation \"%s\" is already member of publication \"%s\"",
+ errmsg("%s \"%s\" is already member of publication \"%s\"",
+ GET_PUBLICATION_REL_STR(is_skip),
RelationGetRelationName(targetrel), pub->name)));
}
check_publication_add_relation(targetrel);
- /* Form a tuple. */
- memset(values, 0, sizeof(values));
- memset(nulls, false, sizeof(nulls));
+ values = (Datum *) palloc0(ncolumns * sizeof(Datum));
+ nulls = (bool *) palloc0(ncolumns * sizeof(bool));
- prrelid = GetNewOidWithIndex(rel, PublicationRelObjectIndexId,
- Anum_pg_publication_rel_oid);
- values[Anum_pg_publication_rel_oid - 1] = ObjectIdGetDatum(prrelid);
- values[Anum_pg_publication_rel_prpubid - 1] =
- ObjectIdGetDatum(pubid);
- values[Anum_pg_publication_rel_prrelid - 1] =
- ObjectIdGetDatum(relid);
+ colid = GET_PUBLICATION_COL_OBJECTID(is_skip);
+ prrelid = GetNewOidWithIndex(rel, PublicationRelObjectIndexId, colid);
+
+ values[colid - 1] = ObjectIdGetDatum(prrelid);
+ colid = GET_PUBLICATION_COL_PUBID(is_skip);
+ values[colid - 1] = ObjectIdGetDatum(pubid);
+ colid = GET_PUBLICATION_COL_RELID(is_skip);
+ values[colid - 1] = ObjectIdGetDatum(relid);
tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
@@ -198,7 +203,7 @@ publication_add_relation(Oid pubid, Relation targetrel,
CatalogTupleInsert(rel, tup);
heap_freetuple(tup);
- ObjectAddressSet(myself, PublicationRelRelationId, prrelid);
+ ObjectAddressSet(myself, GET_PUBLICATION_REL_ID(is_skip), prrelid);
/* Add dependency on the publication */
ObjectAddressSet(referenced, PublicationRelationId, pubid);
@@ -318,7 +323,7 @@ GetRelationPublications(Oid relid)
* should use GetAllTablesPublicationRelations().
*/
List *
-GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
+GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt, bool is_skip)
{
List *result;
Relation pubrelsrel;
@@ -327,28 +332,38 @@ GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
HeapTuple tup;
/* Find all publications associated with the relation. */
- pubrelsrel = table_open(PublicationRelRelationId, AccessShareLock);
+ pubrelsrel = table_open(GET_PUBLICATION_REL_ID(is_skip), AccessShareLock);
ScanKeyInit(&scankey,
- Anum_pg_publication_rel_prpubid,
+ GET_PUBLICATION_COL_PUBID(is_skip),
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(pubid));
- scan = systable_beginscan(pubrelsrel, PublicationRelPrrelidPrpubidIndexId,
+ scan = systable_beginscan(pubrelsrel,
+ GET_PUBLICATION_MULCOL_INDEXID(is_skip),
true, NULL, 1, &scankey);
result = NIL;
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
- Form_pg_publication_rel pubrel;
-
- pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+ Oid relid;
+ if (is_skip)
+ {
+ Form_pg_publication_skip pubskip;
+ pubskip = (Form_pg_publication_skip) GETSTRUCT(tup);
+ relid = pubskip->psrelid;
+ }
+ else
+ {
+ Form_pg_publication_rel pubrel;
+ pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+ relid = pubrel->prrelid;
+ }
- if (get_rel_relkind(pubrel->prrelid) == RELKIND_PARTITIONED_TABLE &&
+ if (get_rel_relkind(relid) == RELKIND_PARTITIONED_TABLE &&
pub_partopt != PUBLICATION_PART_ROOT)
{
- List *all_parts = find_all_inheritors(pubrel->prrelid, NoLock,
- NULL);
+ List *all_parts = find_all_inheritors(relid, NoLock, NULL);
if (pub_partopt == PUBLICATION_PART_ALL)
result = list_concat(result, all_parts);
@@ -368,7 +383,7 @@ GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
Assert(false);
}
else
- result = lappend_oid(result, pubrel->prrelid);
+ result = lappend_oid(result, relid);
}
systable_endscan(scan);
@@ -462,7 +477,8 @@ GetAllTablesPublications(void)
* in the schema specified.
*/
List *
-GetAllTablesPublicationRelations(bool pubviaroot, Oid schemaOid)
+GetAllTablesPublicationRelations(bool pubviaroot, Oid schemaOid,
+ List *pubskiptablelist)
{
Relation classRel;
ScanKeyData key[2];
@@ -492,7 +508,8 @@ GetAllTablesPublicationRelations(bool pubviaroot, Oid schemaOid)
Oid relid = relForm->oid;
if (is_publishable_class(relid, relForm) &&
- !(relForm->relispartition && pubviaroot))
+ !(relForm->relispartition && pubviaroot) &&
+ (!pubskiptablelist || !list_member_oid(pubskiptablelist, relid)))
result = lappend_oid(result, relid);
}
@@ -513,7 +530,8 @@ GetAllTablesPublicationRelations(bool pubviaroot, Oid schemaOid)
Oid relid = relForm->oid;
if (is_publishable_class(relid, relForm) &&
- !relForm->relispartition)
+ !relForm->relispartition &&
+ (!pubskiptablelist || !list_member_oid(pubskiptablelist, relid)))
result = lappend_oid(result, relid);
}
@@ -532,6 +550,11 @@ GetAllSchemasPublicationRelations(Publication *publication)
{
List *result = NIL;
List *pubschemalist = GetPublicationSchemas(publication->oid);
+ List *pubskiptablelist = GetPublicationRelations(publication->oid,
+ publication->pubviaroot ?
+ PUBLICATION_PART_ROOT :
+ PUBLICATION_PART_LEAF,
+ true);
ListCell *cell;
foreach(cell, pubschemalist)
@@ -540,7 +563,8 @@ GetAllSchemasPublicationRelations(Publication *publication)
List *schemaRels = NIL;
schemaRels = GetAllTablesPublicationRelations(publication->pubviaroot,
- schemaOid);
+ schemaOid,
+ pubskiptablelist);
result = list_concat(result, schemaRels);
}
@@ -675,13 +699,23 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
* need those.
*/
if (publication->pubtype == PUBTYPE_ALLTABLES)
+ {
+ List *pubskiptablelist;
+ pubskiptablelist = GetPublicationRelations(publication->oid,
+ publication->pubviaroot ?
+ PUBLICATION_PART_ROOT :
+ PUBLICATION_PART_LEAF,
+ true);
tables = GetAllTablesPublicationRelations(publication->pubviaroot,
- InvalidOid);
+ InvalidOid,
+ pubskiptablelist);
+ }
else if (publication->pubtype == PUBTYPE_TABLE)
tables = GetPublicationRelations(publication->oid,
publication->pubviaroot ?
PUBLICATION_PART_ROOT :
- PUBLICATION_PART_LEAF);
+ PUBLICATION_PART_LEAF,
+ false);
else if (publication->pubtype == PUBTYPE_SCHEMA)
tables = GetAllSchemasPublicationRelations(publication);
funcctx->user_fctx = (void *) tables;
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index e7c27459d8..0af1738f7a 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -662,6 +662,7 @@ AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
case OCLASS_PUBLICATION:
case OCLASS_PUBLICATION_REL:
case OCLASS_PUBLICATION_SCHEMA:
+ case OCLASS_PUBLICATION_SKIP:
case OCLASS_SUBSCRIPTION:
case OCLASS_TRANSFORM:
/* ignore object types that don't have schema-qualified names */
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 34cf049632..b6e4b3c3e4 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -975,6 +975,7 @@ EventTriggerSupportsObjectType(ObjectType obtype)
case OBJECT_PUBLICATION:
case OBJECT_PUBLICATION_REL:
case OBJECT_PUBLICATION_SCHEMA:
+ case OBJECT_PUBLICATION_SKIP:
case OBJECT_ROUTINE:
case OBJECT_RULE:
case OBJECT_SCHEMA:
@@ -1053,6 +1054,7 @@ EventTriggerSupportsObjectClass(ObjectClass objclass)
case OCLASS_PUBLICATION:
case OCLASS_PUBLICATION_REL:
case OCLASS_PUBLICATION_SCHEMA:
+ case OCLASS_PUBLICATION_SKIP:
case OCLASS_SUBSCRIPTION:
case OCLASS_TRANSFORM:
return true;
@@ -2134,6 +2136,7 @@ stringify_grant_objtype(ObjectType objtype)
case OBJECT_PUBLICATION:
case OBJECT_PUBLICATION_REL:
case OBJECT_PUBLICATION_SCHEMA:
+ case OBJECT_PUBLICATION_SKIP:
case OBJECT_ROLE:
case OBJECT_RULE:
case OBJECT_STATISTIC_EXT:
@@ -2217,6 +2220,7 @@ stringify_adefprivs_objtype(ObjectType objtype)
case OBJECT_PUBLICATION:
case OBJECT_PUBLICATION_REL:
case OBJECT_PUBLICATION_SCHEMA:
+ case OBJECT_PUBLICATION_SKIP:
case OBJECT_ROLE:
case OBJECT_RULE:
case OBJECT_STATISTIC_EXT:
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 5fe4b1ad6f..a4a1846f62 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -29,6 +29,7 @@
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_rel.h"
#include "catalog/pg_publication_schema.h"
+#include "catalog/pg_publication_skiprel.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
@@ -53,8 +54,9 @@
static List *OpenTableList(List *tables);
static void CloseTableList(List *rels);
static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
- AlterPublicationStmt *stmt);
-static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
+ AlterPublicationStmt *stmt, bool is_skip);
+static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok,
+ bool is_skip);
static void PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists,
AlterPublicationStmt *stmt);
static void PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok);
@@ -307,7 +309,18 @@ CreatePublication(CreatePublicationStmt *stmt)
Assert(list_length(stmt->tables) > 0);
rels = OpenTableList(stmt->tables);
- PublicationAddTables(puboid, rels, true, NULL);
+ PublicationAddTables(puboid, rels, true, NULL, false);
+ CloseTableList(rels);
+ }
+
+ if (stmt->skiptables)
+ {
+ List *rels;
+
+ Assert(list_length(stmt->skiptables) > 0);
+
+ rels = OpenTableList(stmt->skiptables);
+ PublicationAddTables(puboid, rels, true, NULL, true);
CloseTableList(rels);
}
@@ -423,7 +436,8 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
* trees, not just those explicitly mentioned in the publication.
*/
List *relids = GetPublicationRelations(pubform->oid,
- PUBLICATION_PART_ALL);
+ PUBLICATION_PART_ALL,
+ false);
/*
* We don't want to send too many individual messages, at some point
@@ -456,44 +470,58 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
*/
static void
AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+ HeapTuple tup, bool is_skip)
{
List *rels = NIL;
Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
Oid pubid = pubform->oid;
+ List *tables = is_skip ? stmt->skiptables : stmt->tables;
- /* Check that user is allowed to manipulate the publication tables. */
- if (pubform->pubtype == PUBTYPE_ALLTABLES)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("publication \"%s\" is defined as FOR ALL TABLES",
- NameStr(pubform->pubname)),
- errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
+ if (is_skip)
+ {
+ if (pubform->pubtype == PUBTYPE_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is defined as FOR SCHEMA",
+ NameStr(pubform->pubname)),
+ errdetail("Skip_Tables cannot be added to or dropped from FOR TABLE publications.")));
+ }
+ else
+ {
+ /* Check that user is allowed to manipulate the publication tables. */
+ if (pubform->pubtype == PUBTYPE_ALLTABLES)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is defined as FOR ALL TABLES",
+ NameStr(pubform->pubname)),
+ errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
- if (pubform->pubtype == PUBTYPE_SCHEMA)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("publication \"%s\" is defined as FOR SCHEMA",
- NameStr(pubform->pubname)),
- errdetail("Tables cannot be added to or dropped from FOR SCHEMA publications.")));
+ if (pubform->pubtype == PUBTYPE_SCHEMA)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is defined as FOR SCHEMA",
+ NameStr(pubform->pubname)),
+ errdetail("Tables cannot be added to or dropped from FOR SCHEMA publications.")));
+ }
- Assert(list_length(stmt->tables) > 0);
+ Assert(list_length(tables) > 0);
- rels = OpenTableList(stmt->tables);
+ rels = OpenTableList(tables);
if (stmt->tableAction == DEFELEM_ADD)
{
- PublicationAddTables(pubid, rels, false, stmt);
- if (pubform->pubtype == PUBTYPE_EMPTY)
+ PublicationAddTables(pubid, rels, false, stmt, is_skip);
+ if (!is_skip && pubform->pubtype == PUBTYPE_EMPTY)
UpdatePublicationTypeTupleValue(rel, tup, Anum_pg_publication_pubtype,
PUBTYPE_TABLE);
}
else if (stmt->tableAction == DEFELEM_DROP)
- PublicationDropTables(pubid, rels, false);
+ PublicationDropTables(pubid, rels, false, is_skip);
else /* DEFELEM_SET */
{
List *oldrelids = GetPublicationRelations(pubid,
- PUBLICATION_PART_ROOT);
+ PUBLICATION_PART_ROOT,
+ is_skip);
List *delrels = NIL;
ListCell *oldlc;
@@ -525,13 +553,13 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
}
/* And drop them. */
- PublicationDropTables(pubid, delrels, true);
+ PublicationDropTables(pubid, delrels, true, is_skip);
/*
* Don't bother calculating the difference for adding, we'll catch and
* skip existing ones when doing catalog update.
*/
- PublicationAddTables(pubid, rels, true, stmt);
+ PublicationAddTables(pubid, rels, true, stmt, is_skip);
CloseTableList(delrels);
}
@@ -653,8 +681,10 @@ AlterPublication(AlterPublicationStmt *stmt)
AlterPublicationOptions(stmt, rel, tup);
else if (stmt->schemas)
AlterPublicationSchemas(stmt, rel, tup, pubform);
+ else if (stmt->skiptables)
+ AlterPublicationTables(stmt, rel, tup, true);
else
- AlterPublicationTables(stmt, rel, tup);
+ AlterPublicationTables(stmt, rel, tup, false);
/* Cleanup. */
heap_freetuple(tup);
@@ -665,24 +695,36 @@ AlterPublication(AlterPublicationStmt *stmt)
* Remove relation from publication by mapping OID.
*/
void
-RemovePublicationRelById(Oid proid)
+RemovePublicationRelById(Oid proid, bool is_skip)
{
Relation rel;
HeapTuple tup;
- Form_pg_publication_rel pubrel;
+ Oid relid;
- rel = table_open(PublicationRelRelationId, RowExclusiveLock);
+ rel = table_open(GET_PUBLICATION_REL_ID(is_skip), RowExclusiveLock);
- tup = SearchSysCache1(PUBLICATIONREL, ObjectIdGetDatum(proid));
+ tup = SearchSysCache1(GET_PUBLICATION_SYSCACHE_REL(is_skip),
+ ObjectIdGetDatum(proid));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for publication table %u",
proid);
- pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+ if (is_skip)
+ {
+ Form_pg_publication_skip pubrel;
+ pubrel = (Form_pg_publication_skip) GETSTRUCT(tup);
+ relid = pubrel->psrelid;
+ }
+ else
+ {
+ Form_pg_publication_rel pubrel;
+ pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+ relid = pubrel->prrelid;
+ }
/* Invalidate relcache so that publication info is rebuilt. */
- CacheInvalidateRelcacheByRelid(pubrel->prrelid);
+ CacheInvalidateRelcacheByRelid(relid);
CatalogTupleDelete(rel, &tup->t_self);
@@ -821,11 +863,14 @@ CloseTableList(List *rels)
*/
static void
PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
- AlterPublicationStmt *stmt)
+ AlterPublicationStmt *stmt, bool is_skip)
{
ListCell *lc;
- Assert(!stmt || !stmt->for_all_tables || !stmt->schemas);
+ if (is_skip)
+ Assert(!stmt || !stmt->tables);
+ else
+ Assert(!stmt || !stmt->for_all_tables || !stmt->schemas);
foreach(lc, rels)
{
@@ -837,13 +882,13 @@ PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(rel->rd_rel->relkind),
RelationGetRelationName(rel));
- obj = publication_add_relation(pubid, rel, if_not_exists);
+ obj = publication_add_relation(pubid, rel, if_not_exists, is_skip);
if (stmt)
{
EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
(Node *) stmt);
- InvokeObjectPostCreateHook(PublicationRelRelationId,
+ InvokeObjectPostCreateHook(is_skip ? PublicationSkipRelationId : PublicationRelRelationId,
obj.objectId, 0);
}
}
@@ -886,7 +931,7 @@ PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists,
* Remove listed tables from the publication.
*/
static void
-PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
+PublicationDropTables(Oid pubid, List *rels, bool missing_ok, bool is_skip)
{
ObjectAddress obj;
ListCell *lc;
@@ -897,7 +942,8 @@ PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
Relation rel = (Relation) lfirst(lc);
Oid relid = RelationGetRelid(rel);
- prid = GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
+ prid = GetSysCacheOid2(GET_PUBLICATION_MAP(is_skip),
+ GET_PUBLICATION_COL_OBJECTID(is_skip),
ObjectIdGetDatum(relid),
ObjectIdGetDatum(pubid));
if (!OidIsValid(prid))
@@ -907,11 +953,12 @@ PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("relation \"%s\" is not part of the publication",
+ errmsg("%s \"%s\" is not part of the publication",
+ GET_PUBLICATION_REL_STR(is_skip),
RelationGetRelationName(rel))));
}
- ObjectAddressSet(obj, PublicationRelRelationId, prid);
+ ObjectAddressSet(obj, GET_PUBLICATION_REL_ID(is_skip), prid);
performDeletion(&obj, DROP_CASCADE, 0);
}
}
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index b108b641c5..f32b4e52c9 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -81,6 +81,7 @@ SecLabelSupportsObjectType(ObjectType objtype)
case OBJECT_POLICY:
case OBJECT_PUBLICATION_REL:
case OBJECT_PUBLICATION_SCHEMA:
+ case OBJECT_PUBLICATION_SKIP:
case OBJECT_RULE:
case OBJECT_STATISTIC_EXT:
case OBJECT_TABCONSTRAINT:
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d57cc0bcba..61d18da4b2 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -12141,6 +12141,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
case OCLASS_PUBLICATION:
case OCLASS_PUBLICATION_REL:
case OCLASS_PUBLICATION_SCHEMA:
+ case OCLASS_PUBLICATION_SKIP:
case OCLASS_SUBSCRIPTION:
case OCLASS_TRANSFORM:
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 81e508b7a5..b852de6da8 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -396,6 +396,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <importqual> import_qualification
%type <node> vacuum_relation
%type <selectlimit> opt_select_limit select_limit limit_clause
+%type <list> opt_skip_table_list
%type <list> parse_toplevel stmtmulti routine_body_stmt_list
OptTableElementList TableElementList OptInherit definition
@@ -707,7 +708,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
SAVEPOINT SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW
- SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P
+ SIMILAR SIMPLE SKIP SKIP_TABLE SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P
START STATEMENT STATISTICS STDIN STDOUT STORAGE STORED STRICT_P STRIP_P
SUBSCRIPTION SUBSTRING SUPPORT SYMMETRIC SYSID SYSTEM_P
@@ -9587,11 +9588,11 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec
*
* CREATE PUBLICATION name [WITH options]
*
- * CREATE PUBLICATION FOR ALL TABLES [WITH options]
+ * CREATE PUBLICATION FOR ALL TABLES SKIP_TABLE [WITH options]
*
* CREATE PUBLICATION FOR TABLE [WITH options]
*
- * CREATE PUBLICATION FOR SCHEMA [WITH options]
+ * CREATE PUBLICATION FOR SCHEMA SKIP_TABLE [WITH options]
*****************************************************************************/
CreatePublicationStmt:
@@ -9602,11 +9603,12 @@ CreatePublicationStmt:
n->options = $4;
$$ = (Node *)n;
}
- | CREATE PUBLICATION name FOR ALL TABLES opt_definition
+ | CREATE PUBLICATION name FOR ALL TABLES opt_skip_table_list opt_definition
{
CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
n->pubname = $3;
- n->options = $7;
+ n->options = $8;
+ n->skiptables = (List *)$7;
n->for_all_tables = true;
$$ = (Node *)n;
}
@@ -9618,12 +9620,13 @@ CreatePublicationStmt:
n->tables = (List *)$6;
$$ = (Node *)n;
}
- | CREATE PUBLICATION name FOR SCHEMA schema_list opt_definition
+ | CREATE PUBLICATION name FOR SCHEMA schema_list opt_skip_table_list opt_definition
{
CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
n->pubname = $3;
- n->options = $7;
+ n->options = $8;
n->schemas = (List *)$6;
+ n->skiptables = (List *)$7;
$$ = (Node *)n;
}
;
@@ -9648,6 +9651,10 @@ schema_list: SchemaSpec
{ $$ = lappend($1, $3); }
;
+opt_skip_table_list: SKIP_TABLE relation_expr_list { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
/*****************************************************************************
*
* ALTER PUBLICATION name SET ( options )
@@ -9658,6 +9665,12 @@ schema_list: SchemaSpec
*
* ALTER PUBLICATION name SET TABLE table [, table2]
*
+ * ALTER PUBLICATION name ADD SKIP_TABLE table [, table2]
+ *
+ * ALTER PUBLICATION name DROP SKIP_TABLE table [, table2]
+ *
+ * ALTER PUBLICATION name SET SKIP_TABLE table [, table2]
+ *
* ALTER PUBLICATION name ADD SCHEMA schema [, schema2]
*
* ALTER PUBLICATION name DROP SCHEMA schema [, schema2]
@@ -9697,6 +9710,30 @@ AlterPublicationStmt:
n->tableAction = DEFELEM_DROP;
$$ = (Node *)n;
}
+ | ALTER PUBLICATION name ADD_P SKIP_TABLE relation_expr_list
+ {
+ AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
+ n->pubname = $3;
+ n->skiptables = $6;
+ n->tableAction = DEFELEM_ADD;
+ $$ = (Node *)n;
+ }
+ | ALTER PUBLICATION name SET SKIP_TABLE relation_expr_list
+ {
+ AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
+ n->pubname = $3;
+ n->skiptables = $6;
+ n->tableAction = DEFELEM_SET;
+ $$ = (Node *)n;
+ }
+ | ALTER PUBLICATION name DROP SKIP_TABLE relation_expr_list
+ {
+ AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
+ n->pubname = $3;
+ n->skiptables = $6;
+ n->tableAction = DEFELEM_DROP;
+ $$ = (Node *)n;
+ }
| ALTER PUBLICATION name ADD_P SCHEMA schema_list
{
AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
@@ -15767,6 +15804,7 @@ unreserved_keyword:
| SHOW
| SIMPLE
| SKIP
+ | SKIP_TABLE
| SNAPSHOT
| SQL_P
| STABLE
@@ -16355,6 +16393,7 @@ bare_label_keyword:
| SIMILAR
| SIMPLE
| SKIP
+ | SKIP_TABLE
| SMALLINT
| SNAPSHOT
| SOME
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 1057acd62e..6eb84a00d2 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -1064,23 +1064,30 @@ get_rel_sync_entry(PGOutputData *data, Oid relid)
Publication *pub = lfirst(lc);
bool publish = false;
- if (pub->pubtype == PUBTYPE_ALLTABLES)
+ if (pub->pubtype == PUBTYPE_ALLTABLES ||
+ pub->pubtype == PUBTYPE_SCHEMA)
{
- publish = true;
- if (pub->pubviaroot && am_partition)
- publish_as_relid = llast_oid(get_partition_ancestors(relid));
- }
-
- if (pub->pubtype == PUBTYPE_SCHEMA)
- {
- Oid schemaId = get_rel_namespace(relid);
- List *pubschemas = GetPublicationSchemas(pub->oid);
-
- if (list_member_oid(pubschemas, schemaId))
+ List *skipRels = GetPublicationRelations(pub->oid,
+ pub->pubviaroot ?
+ PUBLICATION_PART_ROOT :
+ PUBLICATION_PART_LEAF,
+ true);
+
+ /* Check if publishing this relation should be skipped */
+ if (!list_member_oid(skipRels, relid))
{
- publish = true;
- if (pub->pubviaroot && am_partition)
- publish_as_relid = llast_oid(get_partition_ancestors(relid));
+ Oid schemaId = (pub->pubtype == PUBTYPE_SCHEMA) ?
+ get_rel_namespace(relid) : InvalidOid;
+ List *pubschemas = (pub->pubtype == PUBTYPE_SCHEMA) ?
+ GetPublicationSchemas(pub->oid) : NIL;
+
+ if (pub->pubtype == PUBTYPE_ALLTABLES ||
+ list_member_oid(pubschemas, schemaId))
+ {
+ publish = true;
+ if (pub->pubviaroot && am_partition)
+ publish_as_relid = llast_oid(get_partition_ancestors(relid));
+ }
}
}
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index b2f8b8add8..10e6b1d783 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -52,6 +52,7 @@
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_rel.h"
#include "catalog/pg_publication_schema.h"
+#include "catalog/pg_publication_skiprel.h"
#include "catalog/pg_range.h"
#include "catalog/pg_replication_origin.h"
#include "catalog/pg_rewrite.h"
@@ -673,6 +674,28 @@ static const struct cachedesc cacheinfo[] = {
},
64
},
+ {PublicationSkipRelationId, /* PUBLICATIONSKIP */
+ PublicationSkipObjectIndexId,
+ 1,
+ {
+ Anum_pg_publication_skiprel_oid,
+ 0,
+ 0,
+ 0
+ },
+ 64
+ },
+ {PublicationSkipRelationId, /* PUBLICATIONSKIPMAP */
+ PublicationSkipPsrelidPspubidIndexId,
+ 2,
+ {
+ Anum_pg_publication_skiprel_psrelid,
+ Anum_pg_publication_skiprel_pspubid,
+ 0,
+ 0
+ },
+ 64
+ },
{RangeRelationId, /* RANGEMULTIRANGE */
RangeMultirangeTypidIndexId,
1,
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 773f038b24..ef70b86f0b 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -255,7 +255,10 @@ getSchemaData(Archive *fout, int *numTablesPtr)
sizeof(PublicationInfo));
pg_log_info("reading publication membership");
- getPublicationTables(fout, tblinfo, numTables);
+ getPublicationTables(fout, tblinfo, numTables, false);
+
+ pg_log_info("reading publication skiptables");
+ getPublicationTables(fout, tblinfo, numTables, true);
pg_log_info("reading publciation schemas");
getPublicationSchemas(fout, nspinfo, numNamespaces);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index dd049da209..110f893283 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -269,7 +269,9 @@ static void dumpBlob(Archive *fout, const BlobInfo *binfo);
static int dumpBlobs(Archive *fout, const void *arg);
static void dumpPolicy(Archive *fout, const PolicyInfo *polinfo);
static void dumpPublication(Archive *fout, const PublicationInfo *pubinfo);
-static void dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo);
+static void dumpPublicationTable(Archive *fout,
+ const PublicationRelInfo *pubrinfo,
+ bool isskip);
static void dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo);
static void dumpDatabase(Archive *AH);
static void dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf,
@@ -4257,7 +4259,8 @@ getPublicationSchemas(Archive *fout, NamespaceInfo nspinfo[], int numSchemas)
* get information about publication membership for dumpable tables.
*/
void
-getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
+getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables,
+ bool isSkip)
{
PQExpBuffer query;
PGresult *res;
@@ -4274,20 +4277,26 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
if (dopt->no_publications || fout->remoteVersion < 100000)
return;
+ if (isSkip && fout->remoteVersion < 140000)
+ return;
+
query = createPQExpBuffer();
/* Collect all publication membership info. */
- appendPQExpBufferStr(query,
- "SELECT tableoid, oid, prpubid, prrelid "
- "FROM pg_catalog.pg_publication_rel");
+ if (isSkip)
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, pspubid, psrelid "
+ "FROM pg_catalog.pg_publication_skiprel");
+ else
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, prpubid, prrelid "
+ "FROM pg_catalog.pg_publication_rel");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
- i_prpubid = PQfnumber(res, "prpubid");
- i_prrelid = PQfnumber(res, "prrelid");
+ i_prpubid = PQfnumber(res, isSkip ? "pspubid" : "prpubid");
+ i_prrelid = PQfnumber(res, isSkip ? "psrelid" : "prrelid");
/* this allocation may be more than we need */
pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo));
@@ -4319,7 +4328,7 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
continue;
/* OK, make a DumpableObject for this relationship */
- pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
+ pubrinfo[j].dobj.objType = (isSkip) ? DO_PUBLICATION_SKIPREL : DO_PUBLICATION_REL;
pubrinfo[j].dobj.catId.tableoid =
atooid(PQgetvalue(res, i, i_tableoid));
pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
@@ -4382,12 +4391,14 @@ dumpPublicationSchema(Archive *fout, PublicationSchemaInfo *pubrinfo)
* dump the definition of the given publication table mapping
*/
static void
-dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo)
+dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo,
+ bool isskip)
{
PublicationInfo *pubinfo = pubrinfo->publication;
TableInfo *tbinfo = pubrinfo->pubtable;
PQExpBuffer query;
char *tag;
+ char *addtabopt = (isskip) ? "SKIP_TABLE" : "TABLE ONLY";
if (!(pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
return;
@@ -4396,8 +4407,8 @@ dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo)
query = createPQExpBuffer();
- appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
- fmtId(pubinfo->dobj.name));
+ appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD %s",
+ fmtId(pubinfo->dobj.name), addtabopt);
appendPQExpBuffer(query, " %s;\n",
fmtQualifiedDumpable(tbinfo));
@@ -4412,7 +4423,7 @@ dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo)
ARCHIVE_OPTS(.tag = tag,
.namespace = tbinfo->dobj.namespace->dobj.name,
.owner = pubinfo->rolname,
- .description = "PUBLICATION TABLE",
+ .description = (isskip) ? "PUBLICATION SKIP TABLE" : "PUBLICATION TABLE",
.section = SECTION_POST_DATA,
.createStmt = query->data));
@@ -10479,11 +10490,14 @@ dumpDumpableObject(Archive *fout, const DumpableObject *dobj)
dumpPublication(fout, (const PublicationInfo *) dobj);
break;
case DO_PUBLICATION_REL:
- dumpPublicationTable(fout, (const PublicationRelInfo *) dobj);
+ dumpPublicationTable(fout, (const PublicationRelInfo *) dobj, false);
break;
case DO_PUBLICATION_SCHEMA:
dumpPublicationSchema(fout, (PublicationSchemaInfo *) dobj);
break;
+ case DO_PUBLICATION_SKIPREL:
+ dumpPublicationTable(fout, (const PublicationRelInfo *) dobj, true);
+ break;
case DO_SUBSCRIPTION:
dumpSubscription(fout, (const SubscriptionInfo *) dobj);
break;
@@ -18681,6 +18695,7 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
case DO_PUBLICATION:
case DO_PUBLICATION_REL:
case DO_PUBLICATION_SCHEMA:
+ case DO_PUBLICATION_SKIPREL:
case DO_SUBSCRIPTION:
/* Post-data objects: must come after the post-data boundary */
addObjectDependency(dobj, postDataBound->dumpId);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index a9db477f25..dd0873b93b 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -82,6 +82,7 @@ typedef enum
DO_PUBLICATION,
DO_PUBLICATION_REL,
DO_PUBLICATION_SCHEMA,
+ DO_PUBLICATION_SKIPREL,
DO_SUBSCRIPTION
} DumpableObjectType;
@@ -744,7 +745,7 @@ extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
extern PublicationInfo *getPublications(Archive *fout,
int *numPublications);
extern void getPublicationTables(Archive *fout, TableInfo tblinfo[],
- int numTables);
+ int numTables, bool isSkip);
extern void getPublicationSchemas(Archive *fout, NamespaceInfo nspinfo[],
int numSchemas);
extern void getSubscriptions(Archive *fout);
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 13a6fcd660..298d3dcbc2 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -83,6 +83,7 @@ enum dbObjectTypePriorities
PRIO_PUBLICATION,
PRIO_PUBLICATION_REL,
PRIO_PUBLICATION_SCHEMA,
+ PRIO_PUBLICATION_SKIPREL,
PRIO_SUBSCRIPTION,
PRIO_DEFAULT_ACL, /* done in ACL pass */
PRIO_EVENT_TRIGGER, /* must be next to last! */
@@ -137,6 +138,7 @@ static const int dbObjectTypePriority[] =
PRIO_PUBLICATION, /* DO_PUBLICATION */
PRIO_PUBLICATION_REL, /* DO_PUBLICATION_REL */
PRIO_PUBLICATION_SCHEMA, /* DO_PUBLICATION_SCHEMA */
+ PRIO_PUBLICATION_SKIPREL, /* DO_PUBLICATION_SKIPREL */
PRIO_SUBSCRIPTION /* DO_SUBSCRIPTION */
};
@@ -1484,6 +1486,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
"PUBLICATION SCHEMA (ID %d OID %u)",
obj->dumpId, obj->catId.oid);
return;
+ case DO_PUBLICATION_SKIPREL:
+ snprintf(buf, bufsize,
+ "PUBLICATION SKPREL (ID %d OID %u)",
+ obj->dumpId, obj->catId.oid);
+ return;
case DO_SUBSCRIPTION:
snprintf(buf, bufsize,
"SUBSCRIPTION (ID %d OID %u)",
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 73417cbfc4..2184d2e27f 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3154,7 +3154,8 @@ describeOneTableDetails(const char *schemaname,
"SELECT p.pubname\n"
"FROM pg_catalog.pg_publication p\n"
" JOIN pg_catalog.pg_publication_schema ps ON p.oid = ps.pspubid AND p.pubtype = 's'\n"
- " JOIN pg_catalog.pg_class pc ON pc.relnamespace = ps.psnspcid AND pc.oid = '%s'\n"
+ " JOIN pg_catalog.pg_class pc ON pc.relnamespace = ps.psnspcid AND pc.oid = '%s' AND\n"
+ " '%s' NOT IN (SELECT psrelid FROM pg_publication_skiprel WHERE pspubid = ps.pspubid)\n"
"UNION ALL\n"
"SELECT pubname\n"
"FROM pg_catalog.pg_publication p\n"
@@ -3163,10 +3164,11 @@ describeOneTableDetails(const char *schemaname,
"UNION ALL\n"
"SELECT pubname\n"
"FROM pg_catalog.pg_publication p\n"
- "WHERE p.pubtype = 'a' \n"
+ "WHERE p.pubtype = 'a' AND\n"
+ " '%s' NOT IN (SELECT psrelid FROM pg_publication_skiprel WHERE pspubid = p.oid)\n"
" AND pg_catalog.pg_relation_is_publishable('%s')\n"
"ORDER BY 1;",
- oid, oid, oid);
+ oid, oid, oid, oid, oid);
}
else
{
@@ -6345,6 +6347,7 @@ describePublications(const char *pattern)
bool has_pubtruncate;
bool has_pubviaroot;
bool has_pubtype;
+ bool has_pubskiptable;
PQExpBufferData title;
printTableContent cont;
@@ -6361,6 +6364,7 @@ describePublications(const char *pattern)
has_pubtruncate = (pset.sversion >= 110000);
has_pubviaroot = (pset.sversion >= 130000);
has_pubtype = (pset.sversion >= 140000);
+ has_pubskiptable = (pset.sversion >= 140000);
initPQExpBuffer(&buf);
@@ -6489,6 +6493,21 @@ describePublications(const char *pattern)
goto error_return;
}
+ if (has_pubskiptable)
+ {
+ printfPQExpBuffer(&buf,
+ "SELECT n.nspname, c.relname\n"
+ "FROM pg_catalog.pg_class c,\n"
+ " pg_catalog.pg_namespace n,\n"
+ " pg_catalog.pg_publication_skiprel ps\n"
+ "WHERE c.relnamespace = n.oid\n"
+ " AND c.oid = ps.psrelid\n"
+ " AND ps.pspubid = '%s'\n"
+ "ORDER BY 1,2", pubid);
+ if (!addFooterToPublicationDesc(&buf, "Skip Tables:", false, &cont))
+ goto error_return;
+ }
+
printTable(&cont, pset.queryFout, false, pset.logfile);
printTableCleanup(&cont);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index ba549e106e..63a672dd1f 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1643,13 +1643,13 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME TO", "SET");
/* ALTER PUBLICATION <name> ADD */
else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD"))
- COMPLETE_WITH("SCHEMA", "TABLE");
+ COMPLETE_WITH("SCHEMA", "SKIP_TABLE", "TABLE");
/* ALTER PUBLICATION <name> DROP */
else if (Matches("ALTER", "PUBLICATION", MatchAny, "DROP"))
- COMPLETE_WITH("SCHEMA", "TABLE");
+ COMPLETE_WITH("SCHEMA", "SKIP_TABLE", "TABLE");
/* ALTER PUBLICATION <name> SET */
else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
- COMPLETE_WITH("(", "SCHEMA", "TABLE");
+ COMPLETE_WITH("(", "SCHEMA", "SKIP_TABLE", "TABLE");
else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|DROP|SET", "SCHEMA"))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas
" UNION SELECT 'CURRENT_SCHEMA'");
@@ -2642,6 +2642,12 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH("FOR TABLE", "FOR ALL TABLES", "FOR SCHEMA", "WITH (");
else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
COMPLETE_WITH("TABLE", "ALL TABLES", "SCHEMA");
+ else if (HeadMatches("CREATE", "PUBLICATION") && TailMatches("FOR", "ALL", "TABLES"))
+ COMPLETE_WITH("SKIP_TABLE");
+ else if (HeadMatches("CREATE", "PUBLICATION") && TailMatches("FOR", "SCHEMA"))
+ COMPLETE_WITH("SKIP_TABLE");
+ else if (HeadMatches("CREATE", "PUBLICATION") && TailMatches("SKIP_TABLE"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* Complete "CREATE PUBLICATION <name> FOR TABLE <table>, ..." */
else if (HeadMatches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 08ec4c79f1..c82fa2765d 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -132,6 +132,7 @@ typedef enum ObjectClass
OCLASS_PUBLICATION, /* pg_publication */
OCLASS_PUBLICATION_REL, /* pg_publication_rel */
OCLASS_PUBLICATION_SCHEMA, /* pg_publication_schema */
+ OCLASS_PUBLICATION_SKIP, /* pg_publication_skip */
OCLASS_SUBSCRIPTION, /* pg_subscription */
OCLASS_TRANSFORM /* pg_transform */
} ObjectClass;
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index f67f92f918..fff16bf76f 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -110,6 +110,33 @@ typedef enum PublicationPartOpt
#define PUBTYPE_SCHEMA 's' /* schema publication */
#define PUBTYPE_EMPTY 'e' /* empty publication */
+#define GET_PUBLICATION_REL_COL_COUNT(is_skip) \
+ (is_skip) ? Natts_pg_publication_skiprel : Natts_pg_publication_rel
+
+#define GET_PUBLICATION_REL_ID(is_skip) \
+ (is_skip) ? PublicationSkipRelationId : PublicationRelRelationId
+
+#define GET_PUBLICATION_MAP(is_skip) \
+ (is_skip) ? PUBLICATIONSKIPMAP : PUBLICATIONRELMAP
+
+#define GET_PUBLICATION_SYSCACHE_REL(is_skip) \
+ (is_skip) ? PUBLICATIONSKIP : PUBLICATIONREL
+
+#define GET_PUBLICATION_COL_OBJECTID(is_skip) \
+ (is_skip) ? Anum_pg_publication_skiprel_oid : Anum_pg_publication_rel_oid
+
+#define GET_PUBLICATION_COL_PUBID(is_skip) \
+ (is_skip) ? Anum_pg_publication_skiprel_pspubid : Anum_pg_publication_rel_prpubid
+
+#define GET_PUBLICATION_COL_RELID(is_skip) \
+ (is_skip) ? Anum_pg_publication_skiprel_psrelid : Anum_pg_publication_rel_prrelid
+
+#define GET_PUBLICATION_MULCOL_INDEXID(is_skip) \
+ (is_skip) ? PublicationSkipPsrelidPspubidIndexId : PublicationRelPrrelidPrpubidIndexId
+
+#define GET_PUBLICATION_REL_STR(is_skip) \
+ (is_skip) ? "skip relation": "relation"
+
/*
* Return the publication type.
*/
diff --git a/src/include/catalog/pg_publication_skiprel.h b/src/include/catalog/pg_publication_skiprel.h
new file mode 100644
index 0000000000..6bfc226c35
--- /dev/null
+++ b/src/include/catalog/pg_publication_skiprel.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_publication_skiprel.h
+ * definition of the system catalog for mappings between relations and
+ * publications (pg_publication_skiprel)
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_publication_skiprel.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PUBLICATION_SKIPREL_H
+#define PG_PUBLICATION_SKIPREL_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_publication_skiprel_d.h"
+
+/* ----------------
+ * pg_publication_skiprel definition. cpp turns this into
+ * typedef struct FormData_pg_publication_skiprel
+ * ----------------
+ */
+CATALOG(pg_publication_skiprel,6122,PublicationSkipRelationId)
+{
+ Oid oid; /* oid */
+ Oid pspubid BKI_LOOKUP(pg_publication); /* Oid of the publication */
+ Oid psrelid BKI_LOOKUP(pg_class); /* Oid of the relation */
+} FormData_pg_publication_skip;
+
+/* ----------------
+ * Form_pg_publication_skip corresponds to a pointer to a tuple with
+ * the format of pg_publication_skip relation.
+ * ----------------
+ */
+typedef FormData_pg_publication_skip *Form_pg_publication_skip;
+
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_skip_oid_index, 6123, on pg_publication_skiprel using btree(oid oid_ops));
+#define PublicationSkipObjectIndexId 6123
+DECLARE_UNIQUE_INDEX(pg_publication_skip_psrelid_prpubid_index, 6124, on pg_publication_skiprel using btree(psrelid oid_ops, pspubid oid_ops));
+#define PublicationSkipPsrelidPspubidIndexId 6124
+
+#endif /* PG_PUBLICATION_SKIP_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 3c2a77d0b0..f3b803cf81 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -21,7 +21,7 @@
extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
extern void AlterPublication(AlterPublicationStmt *stmt);
-extern void RemovePublicationRelById(Oid proid);
+extern void RemovePublicationRelById(Oid proid, bool is_skip);
extern void RemovePublicationSchemaById(Oid psoid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
@@ -31,15 +31,17 @@ extern Publication *GetPublication(Oid pubid);
extern Publication *GetPublicationByName(const char *pubname, bool missing_ok);
extern List *GetRelationPublications(Oid relid);
-extern List *GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt);
+extern List *GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt,
+ bool is_skip);
extern List *GetPublicationSchemas(Oid pubid);
extern List *GetAllTablesPublications(void);
-extern List *GetAllTablesPublicationRelations(bool pubviaroot, Oid schemaOid);
+extern List *GetAllTablesPublicationRelations(bool pubviaroot, Oid schemaOid,
+ List *pubskiptablelist);
extern List *GetAllSchemasPublicationRelations(Publication *publication);
extern bool is_publishable_relation(Relation rel);
extern ObjectAddress publication_add_relation(Oid pubid, Relation targetrel,
- bool if_not_exists);
+ bool if_not_exists, bool is_skip);
extern ObjectAddress publication_add_schema(Oid pubid, Oid schemaoid,
bool if_not_exists);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 169bdce07c..d1a89bc807 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1823,6 +1823,7 @@ typedef enum ObjectType
OBJECT_PUBLICATION,
OBJECT_PUBLICATION_REL,
OBJECT_PUBLICATION_SCHEMA,
+ OBJECT_PUBLICATION_SKIP,
OBJECT_ROLE,
OBJECT_ROUTINE,
OBJECT_RULE,
@@ -3648,6 +3649,7 @@ typedef struct CreatePublicationStmt
char *pubname; /* Name of the publication */
List *options; /* List of DefElem nodes */
List *tables; /* Optional list of tables to add */
+ List *skiptables; /* Optional list of skip tables to add */
bool for_all_tables; /* Special publication for all tables in db */
List *schemas; /* Optional list of schemas */
} CreatePublicationStmt;
@@ -3662,6 +3664,7 @@ typedef struct AlterPublicationStmt
/* parameters used for ALTER PUBLICATION ... ADD/DROP TABLE */
List *tables; /* List of tables to add/drop */
+ List *skiptables; /* List of skip tables to add/drop */
bool for_all_tables; /* Special publication for all tables in db */
DefElemAction tableAction; /* What action to perform with the tables */
List *schemas; /* Optional list of schemas */
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index f836acf876..95b43396ea 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -385,6 +385,7 @@ PG_KEYWORD("show", SHOW, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("similar", SIMILAR, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
PG_KEYWORD("simple", SIMPLE, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("skip", SKIP, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("skip_table", SKIP_TABLE, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("smallint", SMALLINT, COL_NAME_KEYWORD, BARE_LABEL)
PG_KEYWORD("snapshot", SNAPSHOT, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("some", SOME, RESERVED_KEYWORD, BARE_LABEL)
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 1ba295206a..48a284edca 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -81,6 +81,8 @@ enum SysCacheIdentifier
PUBLICATIONRELMAP,
PUBLICATIONSCHEMA,
PUBLICATIONSCHEMAMAP,
+ PUBLICATIONSKIP,
+ PUBLICATIONSKIPMAP,
RANGEMULTIRANGE,
RANGETYPE,
RELNAMENSP,
diff --git a/src/test/regress/expected/oidjoins.out b/src/test/regress/expected/oidjoins.out
index ddb421c394..d34b342248 100644
--- a/src/test/regress/expected/oidjoins.out
+++ b/src/test/regress/expected/oidjoins.out
@@ -262,6 +262,8 @@ NOTICE: checking pg_publication_rel {prpubid} => pg_publication {oid}
NOTICE: checking pg_publication_rel {prrelid} => pg_class {oid}
NOTICE: checking pg_publication_schema {pspubid} => pg_publication {oid}
NOTICE: checking pg_publication_schema {psnspcid} => pg_class {oid}
+NOTICE: checking pg_publication_skiprel {pspubid} => pg_publication {oid}
+NOTICE: checking pg_publication_skiprel {psrelid} => pg_class {oid}
NOTICE: checking pg_subscription {subdbid} => pg_database {oid}
NOTICE: checking pg_subscription {subowner} => pg_authid {oid}
NOTICE: checking pg_subscription_rel {srsubid} => pg_subscription {oid}
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index fe5a038824..675d6503ab 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -141,6 +141,7 @@ pg_proc|t
pg_publication|t
pg_publication_rel|t
pg_publication_schema|t
+pg_publication_skiprel|t
pg_range|t
pg_replication_origin|t
pg_rewrite|t
--
2.25.1