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

Reply via email to