I wonder if trying to add a relation to a publication that it is already a part should be considered a no-op, instead of causing an error (which happens in the ALTER PUBLICATION ADD TABLES case).
create table bar (a int); create publication mypub for table bar; alter publication mypub add table bar; ERROR: relation "bar" is already member of publication "mypub" 2nd command should be a no-op, IMHO. Consider the following (I know we're discussing inheritance elsewhere as well): create table foo (a int); create table baz () inherits (foo); alter table bar inherit foo; alter table mypub add table foo; ERROR: relation "bar" is already member of publication "mypub" There is no way to add foo and children other than bar to mypub without doing so one-by-one. If my proposal to make that a no-op sounds desirable, attached patch implements that. Thanks, Amit
>From 810b7bd26458b625e4f9badb0a032effc954d060 Mon Sep 17 00:00:00 2001 From: amit <amitlangot...@gmail.com> Date: Thu, 13 Apr 2017 19:00:22 +0900 Subject: [PATCH] Fix how duplicate addition to a publication is prevented Treat such an attempt as a no-op instead of causing an error. --- src/backend/catalog/pg_publication.c | 18 ++++-------------- src/backend/commands/publicationcmds.c | 14 +++++++------- src/include/catalog/pg_publication.h | 3 +-- src/test/regress/expected/publication.out | 1 - 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index 9330e2380a..5af9af0f6e 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -101,8 +101,7 @@ is_publishable_class(Oid relid, Form_pg_class reltuple) * Insert new publication / relation mapping. */ ObjectAddress -publication_add_relation(Oid pubid, Relation targetrel, - bool if_not_exists) +publication_add_relation(Oid pubid, Relation targetrel) { Relation rel; HeapTuple tup; @@ -110,29 +109,20 @@ publication_add_relation(Oid pubid, Relation targetrel, bool nulls[Natts_pg_publication_rel]; Oid relid = RelationGetRelid(targetrel); Oid prrelid; - Publication *pub = GetPublication(pubid); ObjectAddress myself, referenced; rel = heap_open(PublicationRelRelationId, 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 target relation is already a part of the publication, nothing to + * to do here. */ if (SearchSysCacheExists2(PUBLICATIONRELMAP, ObjectIdGetDatum(relid), ObjectIdGetDatum(pubid))) { heap_close(rel, RowExclusiveLock); - - if (if_not_exists) - return InvalidObjectAddress; - - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("relation \"%s\" is already member of publication \"%s\"", - RelationGetRelationName(targetrel), pub->name))); + return InvalidObjectAddress; } check_publication_add_relation(targetrel); diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index 541da7ee12..100d2ab9b5 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -52,7 +52,7 @@ static List *OpenTableList(List *tables); static void CloseTableList(List *rels); -static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists, +static void PublicationAddTables(Oid pubid, List *rels, AlterPublicationStmt *stmt); static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok); @@ -232,7 +232,7 @@ CreatePublication(CreatePublicationStmt *stmt) Assert(list_length(stmt->tables) > 0); rels = OpenTableList(stmt->tables); - PublicationAddTables(puboid, rels, true, NULL); + PublicationAddTables(puboid, rels, NULL); CloseTableList(rels); } @@ -357,7 +357,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel, rels = OpenTableList(stmt->tables); if (stmt->tableAction == DEFELEM_ADD) - PublicationAddTables(pubid, rels, false, stmt); + PublicationAddTables(pubid, rels, stmt); else if (stmt->tableAction == DEFELEM_DROP) PublicationDropTables(pubid, rels, false); else /* DEFELEM_SET */ @@ -399,7 +399,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel, * 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, stmt); CloseTableList(delrels); } @@ -595,7 +595,7 @@ CloseTableList(List *rels) * Add listed tables to the publication. */ static void -PublicationAddTables(Oid pubid, List *rels, bool if_not_exists, +PublicationAddTables(Oid pubid, List *rels, AlterPublicationStmt *stmt) { ListCell *lc; @@ -612,8 +612,8 @@ PublicationAddTables(Oid pubid, List *rels, bool if_not_exists, aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, RelationGetRelationName(rel)); - obj = publication_add_relation(pubid, rel, if_not_exists); - if (stmt) + obj = publication_add_relation(pubid, rel); + if (obj.objectId != InvalidOid) { EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress, (Node *) stmt); diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h index f3c4f3932b..07407f6e94 100644 --- a/src/include/catalog/pg_publication.h +++ b/src/include/catalog/pg_publication.h @@ -93,8 +93,7 @@ extern List *GetPublicationRelations(Oid pubid); extern List *GetAllTablesPublications(void); extern List *GetAllTablesPublicationRelations(void); -extern ObjectAddress publication_add_relation(Oid pubid, Relation targetrel, - bool if_not_exists); +extern ObjectAddress publication_add_relation(Oid pubid, Relation targetrel); extern Oid get_publication_oid(const char *pubname, bool missing_ok); extern char *get_publication_name(Oid pubid); diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out index 0964718a60..7a84cc71a7 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -78,7 +78,6 @@ DETAIL: Only tables can be added to publications. CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_tbl1, pub_test.testpub_nopk; -- fail - already added ALTER PUBLICATION testpub_fortbl ADD TABLE testpub_tbl1; -ERROR: relation "testpub_tbl1" is already member of publication "testpub_fortbl" -- fail - already added CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_tbl1; ERROR: publication "testpub_fortbl" already exists -- 2.11.0
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers