Here is a "fixup" patch for
0002-Add-PUBLICATION-catalogs-and-DDL-v11.patch.gz with some minor fixes.

Two issues that should be addressed:

1. I think ALTER PUBLICATION does not need to require CREATE privilege
on the database.  That should be easy to change.

2. By requiring only SELECT privilege to include a table in a
publication, someone could include a table without replica identity into
a publication and thus prevent updates to the table.

A while ago I had been working on a patch to create a new PUBLICATION
privilege for this purpose.  I have attached the in-progress patch here.
 We could either finish that up and include it, or commit your patch
initially with requiring superuser and then refine the permissions later.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 38aba08eb00ffc0b1f0d52a38864f825435a1694 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pete...@gmx.net>
Date: Thu, 8 Dec 2016 12:00:00 -0500
Subject: [PATCH] fixup! Add PUBLICATION catalogs and DDL

---
 doc/src/sgml/catalogs.sgml                | 35 ++++++++++-------------
 doc/src/sgml/ref/alter_publication.sgml   | 41 +++++++++------------------
 doc/src/sgml/ref/create_publication.sgml  | 46 +++++++++++++++++--------------
 doc/src/sgml/ref/drop_publication.sgml    |  6 ++--
 doc/src/sgml/ref/psql-ref.sgml            |  6 ++--
 src/backend/catalog/Makefile              |  2 +-
 src/backend/catalog/dependency.c          |  4 +--
 src/backend/catalog/objectaddress.c       | 25 +++++++----------
 src/backend/catalog/pg_publication.c      | 27 ++++++++++--------
 src/backend/commands/publicationcmds.c    | 12 ++++----
 src/backend/commands/tablecmds.c          |  9 +++---
 src/backend/parser/gram.y                 |  2 +-
 src/backend/utils/cache/relcache.c        |  2 +-
 src/backend/utils/cache/syscache.c        |  2 +-
 src/bin/pg_dump/pg_dump.c                 |  3 --
 src/bin/psql/tab-complete.c               |  8 +++---
 src/test/regress/expected/publication.out | 22 +++++++--------
 17 files changed, 115 insertions(+), 137 deletions(-)

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index aacd4bcb23..5213aa4f5e 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5149,12 +5149,11 @@ <title><structname>pg_publication</structname></title>
   </indexterm>
 
   <para>
-   The <structname>pg_publication</structname> catalog contains
-   all publications created in the database.
+   The catalog <structname>pg_publication</structname> contains all
+   publications created in the database.
   </para>
 
   <table>
-
    <title><structname>pg_publication</structname> Columns</title>
 
    <tgroup cols="4">
@@ -5179,7 +5178,7 @@ <title><structname>pg_publication</structname> Columns</title>
       <entry><structfield>pubname</structfield></entry>
       <entry><type>Name</type></entry>
       <entry></entry>
-      <entry>A unique, database-wide identifier for the publication.</entry>
+      <entry>Name of the publication</entry>
      </row>
 
      <row>
@@ -5202,26 +5201,25 @@ <title><structname>pg_publication</structname> Columns</title>
       <entry><structfield>pubinsert</structfield></entry>
       <entry><type>bool</type></entry>
       <entry></entry>
-      <entry>If true, INSERT operations are replicated for tables in the
-       publication.</entry>
+      <entry>If true, <command>INSERT</command> operations are replicated for
+       tables in the publication.</entry>
      </row>
 
      <row>
       <entry><structfield>pubupdate</structfield></entry>
       <entry><type>bool</type></entry>
       <entry></entry>
-      <entry>If true, UPDATE operations are replicated for tables in the
-       publication.</entry>
+      <entry>If true, <command>UPDATE</command> operations are replicated for
+       tables in the publication.</entry>
      </row>
 
      <row>
       <entry><structfield>pubdelete</structfield></entry>
       <entry><type>bool</type></entry>
       <entry></entry>
-      <entry>If true, DELETE operations are replicated for tables in the
-       publication.</entry>
+      <entry>If true, <command>DELETE</command> operations are replicated for
+       tables in the publication.</entry>
      </row>
-
     </tbody>
    </tgroup>
   </table>
@@ -5235,13 +5233,12 @@ <title><structname>pg_publication_rel</structname></title>
   </indexterm>
 
   <para>
-   The <structname>pg_publication_rel</structname> catalog contains
-   mapping between tables and publications in the database. This is many to
-   many mapping.
+   The catalog <structname>pg_publication_rel</structname> contains the
+   mapping between relations and publications in the database.  This is a
+   many-to-many mapping.
   </para>
 
   <table>
-
    <title><structname>pg_publication_rel</structname> Columns</title>
 
    <tgroup cols="4">
@@ -5255,21 +5252,19 @@ <title><structname>pg_publication_rel</structname> Columns</title>
     </thead>
 
     <tbody>
-
      <row>
       <entry><structfield>prpubid</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-publication"><structname>pg_publication</structname></link>.oid</literal></entry>
-      <entry>Publication reference.</entry>
+      <entry>Reference to publication</entry>
      </row>
 
      <row>
       <entry><structfield>prrelid</structfield></entry>
-      <entry><type>bool</type></entry>
+      <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
-      <entry>Relation reference.</entry>
+      <entry>Reference to relation</entry>
      </row>
-
     </tbody>
    </tgroup>
   </table>
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index c17666c97f..eb8cb07126 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -40,21 +40,20 @@ <title>Description</title>
 
   <para>
    The first variant of this command listed in the synopsis can change
-   all of the publication attributes specified in
-   <xref linkend="sql-createpublication">.
-   Attributes not mentioned in the command retain their previous settings.
-   Database superusers can change any of these settings for any role.
+   all of the publication properties specified in
+   <xref linkend="sql-createpublication">.  Properties not mentioned in the
+   command retain their previous settings.  Database superusers can change any
+   of these settings for any role.
   </para>
 
   <para>
-   The other variants of this command deal with table membership in the
-   publication. The <literal>SET TABLE</literal> clause will replace
-   the current list of tables in the publication with the specified one.
-   Similarly the <literal>ADD TABLE</literal> and
-   <literal>DROP TABLE</literal> will add and remove one or more table from
-   publication.
+   The other variants of this command deal with the table membership of the
+   publication.  The <literal>SET TABLE</literal> clause will replace the
+   list of tables in the publication with the specified one.
+   The <literal>ADD TABLE</literal> and
+   <literal>DROP TABLE</literal> will add and remove one or more tables from
+   the publication.
   </para>
-
  </refsect1>
 
  <refsect1>
@@ -65,8 +64,7 @@ <title>Parameters</title>
     <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
-      The name of an existing publication whose attributes are to be
-      altered.
+      The name of an existing publication whose definition is to be altered.
      </para>
     </listitem>
    </varlistentry>
@@ -80,9 +78,8 @@ <title>Parameters</title>
     <term><literal>NOPUBLISH DELETE</literal></term>
     <listitem>
      <para>
-      These clauses alter attributes originally set by
-      <xref linkend="SQL-CREATEPUBLICATION">. For more information, see the
-      <command>CREATE PUBLICATION</command> reference page.
+      These clauses alter properties originally set by
+      <xref linkend="SQL-CREATEPUBLICATION">.  See there for more information.
      </para>
     </listitem>
    </varlistentry>
@@ -95,16 +92,6 @@ <title>Parameters</title>
      </para>
     </listitem>
    </varlistentry>
-
-   <varlistentry>
-    <term><replaceable class="parameter">schema_name</replaceable></term>
-    <listitem>
-     <para>
-      Name of a schema.
-     </para>
-    </listitem>
-   </varlistentry>
-
   </variablelist>
  </refsect1>
 
@@ -124,7 +111,6 @@ <title>Examples</title>
 ALTER PUBLICATION mypublication ADD TABLE users, departments;
 </programlisting>
   </para>
-
  </refsect1>
 
  <refsect1>
@@ -144,5 +130,4 @@ <title>See Also</title>
    <member><xref linkend="sql-droppublication"></member>
   </simplelist>
  </refsect1>
-
 </refentry>
diff --git a/doc/src/sgml/ref/create_publication.sgml b/doc/src/sgml/ref/create_publication.sgml
index a6bd3602fa..87becb4c0a 100644
--- a/doc/src/sgml/ref/create_publication.sgml
+++ b/doc/src/sgml/ref/create_publication.sgml
@@ -16,7 +16,7 @@
 
  <refnamediv>
   <refname>CREATE PUBLICATION</refname>
-  <refpurpose>define new publication</refpurpose>
+  <refpurpose>define a new publication</refpurpose>
  </refnamediv>
 
  <refsynopsisdiv>
@@ -39,14 +39,14 @@ <title>Description</title>
 
   <para>
    <command>CREATE PUBLICATION</command> adds a new publication
-   into the current database. The publication name must be distinct from
+   into the current database.  The publication name must be distinct from
    the name of any existing publication in the current database.
   </para>
 
   <para>
-   A publication is essentially a group of tables intended for managing
-   logical replication.
-   </para>
+   A publication is essentially a group of tables whose data changes are
+   intended to be replicated through logical replication.
+  </para>
  </refsect1>
 
  <refsect1>
@@ -66,7 +66,7 @@ <title>Parameters</title>
     <term><literal>FOR TABLE</literal></term>
     <listitem>
      <para>
-      Specifies optional list of tables to add to the publication.
+      Specifies a list of tables to add to the publication.
      </para>
     </listitem>
    </varlistentry>
@@ -75,8 +75,8 @@ <title>Parameters</title>
     <term><literal>FOR ALL TABLES</literal></term>
     <listitem>
      <para>
-      Marks the publication as one that replicates changes for all
-      tables in the database, including the ones created in the future.
+      Marks the publication as one that replicates changes for all tables in
+      the database, including tables created in the future.
      </para>
     </listitem>
    </varlistentry>
@@ -124,8 +124,14 @@ <title>Parameters</title>
   <title>Notes</title>
 
   <para>
-   This operation itself does start replication. It only defines grouping
-   and filtering logic for future subscribers.
+   If neither <literal>FOR TABLE</literal> nor <literal>FOR ALL
+   TABLES</literal> is specified, then the publication starts out with an
+   empty set of tables.  That is useful if tables are to be added later.
+  </para>
+
+  <para>
+   The creation of a publication does not start replication.  It only defines
+   a grouping and filtering logic for future subscribers.
   </para>
 
   <para>
@@ -135,23 +141,23 @@ <title>Notes</title>
   </para>
 
   <para>
-   To add table to a publication, the invoking user must have
+   To add a table to a publication, the invoking user must have
    <command>SELECT</command> privilege on given table.  The
    <command>FOR ALL TABLES</command> clause requires superuser.
   </para>
 
   <para>
-   The tables added to a publication which publishes <command>UPDATE</command>
+   The tables added to a publication that publishes <command>UPDATE</command>
    and/or <command>DELETE</command> operations must have
-   <literal>REPLICA IDENTITY</> defined, otherwise these operations will not
-   be allowed on them.
+   <literal>REPLICA IDENTITY</> defined.  Otherwise those operations will be
+   disallowed on those tables.
   </para>
 
   <para>
-   For the <command>INSERT ... ON CONFLICT</> command, the publication will
-   publish resulting tuple operation. So depending of the outcome, it may
-   be published as either <command>INSERT</command> or
-   <command>UPDATE</command> or it may not be published at all.
+   For an <command>INSERT ... ON CONFLICT</> command, the publication will
+   publish the operation that actually results from the command.  So depending
+   of the outcome, it may be published as either <command>INSERT</command> or
+   <command>UPDATE</command>, or it may not be published at all.
   </para>
 
   <para>
@@ -171,12 +177,11 @@ <title>Examples</title>
   </para>
 
   <para>
-   Create an insert only publication:
+   Create an insert-only publication:
 <programlisting>
 CREATE PUBLICATION insert_only WITH (NOPUBLISH UPDATE, NOPUBLISH DELETE);
 </programlisting>
   </para>
-
  </refsect1>
 
  <refsect1>
@@ -196,5 +201,4 @@ <title>See Also</title>
    <member><xref linkend="sql-droppublication"></member>
   </simplelist>
  </refsect1>
-
 </refentry>
diff --git a/doc/src/sgml/ref/drop_publication.sgml b/doc/src/sgml/ref/drop_publication.sgml
index 6c0e3ba959..d05d522041 100644
--- a/doc/src/sgml/ref/drop_publication.sgml
+++ b/doc/src/sgml/ref/drop_publication.sgml
@@ -16,7 +16,7 @@
 
  <refnamediv>
   <refname>DROP PUBLICATION</refname>
-  <refpurpose>remove an existing publication</refpurpose>
+  <refpurpose>remove a publication</refpurpose>
  </refnamediv>
 
  <refsynopsisdiv>
@@ -29,7 +29,8 @@
   <title>Description</title>
 
   <para>
-   <command>DROP PUBLICATION</command> removes publications from the database.
+   <command>DROP PUBLICATION</command> removes an existing publication from
+   the database.
   </para>
 
   <para>
@@ -82,5 +83,4 @@ <title>See Also</title>
    <member><xref linkend="sql-alterpublication"></member>
   </simplelist>
  </refsect1>
-
 </refentry>
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 678b6f7fe5..93d024b4c7 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1604,11 +1604,11 @@ <title>Meta-Commands</title>
         <term><literal>\dRp[+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
         <listitem>
         <para>
-        List replication publications.
+        Lists replication publications.
         If <replaceable class="parameter">pattern</replaceable> is
-        specified, only publications whose names match the pattern are
+        specified, only those publications whose names match the pattern are
         listed.
-        If <literal>+</literal> is appended to the command name, tables
+        If <literal>+</literal> is appended to the command name, the tables
         associated with each publication are shown as well.
         </para>
         </listitem>
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 5866097dd7..73b514c04c 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -15,7 +15,7 @@ OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \
        pg_constraint.o pg_conversion.o \
        pg_depend.o pg_enum.o pg_inherits.o pg_largeobject.o pg_namespace.o \
        pg_operator.o pg_proc.o pg_publication.o pg_range.o \
-	   pg_db_role_setting.o pg_shdepend.o pg_type.o storage.o toasting.o
+       pg_db_role_setting.o pg_shdepend.o pg_type.o storage.o toasting.o
 
 BKIFILES = postgres.bki postgres.description postgres.shdescription
 
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index d72c948342..4e5b68f8b9 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -166,8 +166,8 @@ static const Oid object_classes[] = {
 	ExtensionRelationId,		/* OCLASS_EXTENSION */
 	EventTriggerRelationId,		/* OCLASS_EVENT_TRIGGER */
 	PolicyRelationId,			/* OCLASS_POLICY */
-	PublicationRelationId,		/* OCLASS_PUBCLICATION */
-	PublicationRelRelationId,	/* OCLASS_PUBCLICATION_REL */
+	PublicationRelationId,		/* OCLASS_PUBLICATION */
+	PublicationRelRelationId,	/* OCLASS_PUBLICATION_REL */
 	TransformRelationId			/* OCLASS_TRANSFORM */
 };
 
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 8fb5c0a683..59249804bd 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -1781,9 +1781,8 @@ get_object_address_usermapping(List *objname, List *objargs, bool missing_ok)
 }
 
 /*
- * Find the ObjectAddress for a publication relation.
- * The objname parameter is relation name while objargs contains publication
- * name.
+ * Find the ObjectAddress for a publication relation.  The objname parameter
+ * is the relation name; objargs contains the publication name.
  */
 static ObjectAddress
 get_object_address_publication_rel(List *objname, List *objargs,
@@ -2267,6 +2266,11 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 									format_type_be(targettypeid))));
 			}
 			break;
+		case OBJECT_PUBLICATION:
+			if (!pg_publication_ownercheck(address.objectId, roleid))
+				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PUBLICATION,
+							   NameListToString(objname));
+			break;
 		case OBJECT_TRANSFORM:
 			{
 				TypeName   *typename = (TypeName *) linitial(objname);
@@ -2315,7 +2319,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 		case OBJECT_TSPARSER:
 		case OBJECT_TSTEMPLATE:
 		case OBJECT_ACCESS_METHOD:
-		case OBJECT_PUBLICATION:
 			/* We treat these object types as being owned by superusers */
 			if (!superuser_arg(roleid))
 				ereport(ERROR,
@@ -3278,16 +3281,8 @@ getObjectDescription(const ObjectAddress *object)
 
 		case OCLASS_PUBLICATION:
 			{
-				HeapTuple	tup;
-
-				tup = SearchSysCache1(PUBLICATIONOID,
-									  ObjectIdGetDatum(object->objectId));
-				if (!HeapTupleIsValid(tup))
-					elog(ERROR, "cache lookup failed for publication %u",
-						 object->objectId);
-				appendStringInfo(&buffer, _("publicaton %s"),
-				   NameStr(((Form_pg_publication) GETSTRUCT(tup))->pubname));
-				ReleaseSysCache(tup);
+				appendStringInfo(&buffer, _("publication %s"),
+								 get_publication_name(object->objectId));
 				break;
 			}
 
@@ -4802,7 +4797,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 				prform = (Form_pg_publication_rel) GETSTRUCT(tup);
 				pubname = get_publication_name(prform->prpubid);
 
-				appendStringInfo(&buffer, _("%s in publication %s"),
+				appendStringInfo(&buffer, _("publication table %s in publication %s"),
 								 get_rel_name(prform->prrelid), pubname);
 
 				if (objname)
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index d77db2043f..e3560b7f94 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -1,9 +1,9 @@
 /*-------------------------------------------------------------------------
  *
  * publication.c
- *		publication C api manipulation
+ *		publication C API manipulation
  *
- * Copyright (c) 2015, PostgreSQL Global Development Group
+ * Copyright (c) 2016, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
  *		publication.c
@@ -60,23 +60,25 @@ check_publication_add_relation(Relation targetrel)
 	if (RelationGetForm(targetrel)->relkind != RELKIND_RELATION)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("only tables can be added to publication"),
-				 errdetail("%s is not a table",
-						   RelationGetRelationName(targetrel))));
+				 errmsg("\"%s\" is not a table",
+						RelationGetRelationName(targetrel)),
+				 errdetail("Only tables can be added to publications.")));
 
 	/* Can't be system table */
 	if (IsCatalogRelation(targetrel))
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("only user tables can be added to publication"),
-				 errdetail("%s is a system table",
-						   RelationGetRelationName(targetrel))));
+				 errmsg("\"%s\" is a system table",
+						RelationGetRelationName(targetrel)),
+				 errdetail("System tables cannot be added to publications.")));
 
 	/* UNLOGGED and TEMP relations cannot be part of publication. */
 	if (!RelationNeedsWAL(targetrel))
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("UNLOGGED and TEMP relations cannot be replicated")));
+				 errmsg("table \"%s\" cannot be replicated",
+						RelationGetRelationName(targetrel)),
+				 errdetail("Temporary and unlogged relations cannot be replicated.")));
 }
 
 /*
@@ -125,8 +127,8 @@ publication_add_relation(Oid pubid, Relation targetrel,
 			return InvalidObjectAddress;
 
 		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("relation %s is already member of publication %s",
+				(errcode(ERRCODE_DUPLICATE_OBJECT),
+				 errmsg("relation \"%s\" is already member of publication \"%s\"",
 						RelationGetRelationName(targetrel), pub->name)));
 	}
 
@@ -148,8 +150,9 @@ publication_add_relation(Oid pubid, Relation targetrel,
 	CatalogUpdateIndexes(rel, tup);
 	heap_freetuple(tup);
 
-	/* Add dependency on the publication */
 	ObjectAddressSet(myself, PublicationRelRelationId, prrelid);
+
+	/* Add dependency on the publication */
 	ObjectAddressSet(referenced, PublicationRelationId, pubid);
 	recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
 
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index ebdef06665..bf16b653b1 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -3,7 +3,7 @@
  * publicationcmds.c
  *		publication manipulation
  *
- * Copyright (c) 2015, PostgreSQL Global Development Group
+ * Copyright (c) 2016, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
  *		publicationcmds.c
@@ -240,8 +240,6 @@ CreatePublication(CreatePublicationStmt *stmt)
 
 	heap_close(rel, RowExclusiveLock);
 
-	CommandCounterIncrement();
-
 	return myself;
 }
 
@@ -320,10 +318,10 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
 	/* Check that user is allowed to manipulate the publication tables. */
 	if (pubform->puballtables)
 		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("tables cannot be added to or dropped from FOR ALL TABLES publications"),
-				 errdetail("publication %s is defined as FOR ALL TABLES",
-						   NameStr(pubform->pubname))));
+				(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.")));
 
 	Assert(list_length(stmt->tables) > 0);
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c9dbe1857f..a64e2ca2de 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -11341,11 +11341,12 @@ ATPrepChangePersistence(Relation rel, bool toLogged)
 	 * UNLOGGED as UNLOGGED tables can't be published.
 	 */
 	if (!toLogged &&
-		list_length(GetRelationPublications(RelationGetRelid(rel))))
+		list_length(GetRelationPublications(RelationGetRelid(rel))) > 0)
 		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
-				 errmsg("could not change table \"%s\" to unlogged because it is published",
-						RelationGetRelationName(rel))));
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("cannot change table \"%s\" to unlogged because it is part of a publication",
+						RelationGetRelationName(rel)),
+				 errdetail("Unlogged relations cannot be replicated.")));
 
 	/*
 	 * Check existing foreign key constraints to preserve the invariant that
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0e2aef1fb0..a7f220791a 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -384,7 +384,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <list>	group_by_list
 %type <node>	group_by_item empty_grouping_set rollup_clause cube_clause
 %type <node>	grouping_sets_clause
-%type <node>    opt_publication_for_tables publication_for_tables
+%type <node>	opt_publication_for_tables publication_for_tables
 
 %type <list>	opt_fdw_options fdw_options
 %type <defelt>	fdw_option
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 96b6c8b09a..07fdca16cd 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -4698,7 +4698,7 @@ GetRelationPublicationActions(Relation relation)
 		relation->rd_pubactions = NULL;
 	}
 
-	/* Now save copy of the bitmap in the relcache entry. */
+	/* Now save copy of the actions in the relcache entry. */
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 	relation->rd_pubactions = palloc(sizeof(PublicationActions));
 	memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index c7a4127402..395d379be6 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -49,9 +49,9 @@
 #include "catalog/pg_operator.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_range.h"
 #include "catalog/pg_publication.h"
 #include "catalog/pg_publication_rel.h"
+#include "catalog/pg_range.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_seclabel.h"
 #include "catalog/pg_shdepend.h"
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 4bcde1bede..d173f59a74 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -3293,9 +3293,6 @@ getPublications(Archive *fout)
 
 	query = createPQExpBuffer();
 
-	if (g_verbose)
-		write_msg(NULL, "reading publications\n");
-
 	resetPQExpBuffer(query);
 
 	/* Get the publications. */
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index d7216a06b8..d6b333a72d 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -960,7 +960,7 @@ static const pgsql_thing_t words_after_create[] = {
 	{"OWNED", NULL, NULL, THING_NO_CREATE},		/* for DROP OWNED BY ... */
 	{"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
 	{"POLICY", NULL, NULL},
-	{"bPUBLICATION", NULL, NULL},
+	{"PUBLICATION", NULL, NULL},
 	{"ROLE", Query_for_list_of_roles},
 	{"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
 	{"SCHEMA", Query_for_list_of_schemas},
@@ -2195,9 +2195,9 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 	/* Complete "CREATE PUBLICATION <name> [...] WITH" */
 	else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
-		COMPLETE_WITH_LIST6("REPLICATE_INSERT", "NOREPLICATE_INSERT",
-							"REPLICATE_UPDATE", "NOREPLICATE_UPDATE",
-							"REPLICATE_DELETE", "NOREPLICATE_DELETE");
+		COMPLETE_WITH_LIST2("PUBLISH", "NOPUBLISH");
+	else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches3("WITH", "(", MatchAny))
+		COMPLETE_WITH_LIST3("INSERT", "UPDATE", "DELETE");
 
 /* CREATE RULE */
 	/* Complete "CREATE RULE <sth>" with "AS ON" */
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index b281649bc8..ebbb8c0880 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -33,16 +33,16 @@ ALTER PUBLICATION testpub_foralltables WITH (publish update);
 CREATE TABLE testpub_tbl2 (id serial primary key, data text);
 -- fail - can't add to for all tables publication
 ALTER PUBLICATION testpub_foralltables ADD TABLE testpub_tbl2;
-ERROR:  tables cannot be added to or dropped from FOR ALL TABLES publications
-DETAIL:  publication testpub_foralltables is defined as FOR ALL TABLES
+ERROR:  publication "testpub_foralltables" is defined as FOR ALL TABLES
+DETAIL:  Tables cannot be added to or dropped from FOR ALL TABLES publications.
 -- fail - can't drop from all tables publication
 ALTER PUBLICATION testpub_foralltables DROP TABLE testpub_tbl2;
-ERROR:  tables cannot be added to or dropped from FOR ALL TABLES publications
-DETAIL:  publication testpub_foralltables is defined as FOR ALL TABLES
+ERROR:  publication "testpub_foralltables" is defined as FOR ALL TABLES
+DETAIL:  Tables cannot be added to or dropped from FOR ALL TABLES publications.
 -- fail - can't add to for all tables publication
 ALTER PUBLICATION testpub_foralltables SET TABLE pub_test.testpub_nopk;
-ERROR:  tables cannot be added to or dropped from FOR ALL TABLES publications
-DETAIL:  publication testpub_foralltables is defined as FOR ALL TABLES
+ERROR:  publication "testpub_foralltables" is defined as FOR ALL TABLES
+DETAIL:  Tables cannot be added to or dropped from FOR ALL TABLES publications.
 SELECT pubname, puballtables FROM pg_publication WHERE pubname = 'testpub_foralltables';
        pubname        | puballtables 
 ----------------------+--------------
@@ -64,12 +64,12 @@ DROP TABLE testpub_tbl2;
 DROP PUBLICATION testpub_foralltables;
 -- fail - view
 CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_view;
-ERROR:  only tables can be added to publication
-DETAIL:  testpub_view is not a table
+ERROR:  "testpub_view" is not a table
+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
+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
@@ -84,8 +84,8 @@ Tables:
 
 -- fail - view
 ALTER PUBLICATION testpub_default ADD TABLE testpub_view;
-ERROR:  only tables can be added to publication
-DETAIL:  testpub_view is not a table
+ERROR:  "testpub_view" is not a table
+DETAIL:  Only tables can be added to publications.
 ALTER PUBLICATION testpub_default ADD TABLE testpub_tbl1;
 ALTER PUBLICATION testpub_default SET TABLE testpub_tbl1;
 ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_nopk;
-- 
2.11.0

From ce569a3f72fd04955e514585157cff207268a81c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pete...@gmx.net>
Date: Wed, 5 Oct 2016 12:00:00 -0400
Subject: [PATCH] Add PUBLICATION privilege

---
 doc/src/sgml/ref/grant.sgml              | 15 ++++++++++--
 src/backend/catalog/aclchk.c             |  4 ++++
 src/backend/commands/publicationcmds.c   | 10 ++++++++
 src/backend/utils/adt/acl.c              |  9 +++++++
 src/bin/pg_dump/dumputils.c              |  2 ++
 src/include/nodes/parsenodes.h           |  3 ++-
 src/include/utils/acl.h                  |  5 ++--
 src/test/regress/expected/dependency.out | 22 +++++++++---------
 src/test/regress/expected/privileges.out | 40 ++++++++++++++++----------------
 src/test/regress/sql/dependency.sql      |  2 +-
 10 files changed, 75 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index d8ca39f869..6b0fbb1ff4 100644
--- a/doc/src/sgml/ref/grant.sgml
+++ b/doc/src/sgml/ref/grant.sgml
@@ -21,7 +21,7 @@
 
  <refsynopsisdiv>
 <synopsis>
-GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
+GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | PUBLICATION }
     [, ...] | ALL [ PRIVILEGES ] }
     ON { [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
          | ALL TABLES IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] }
@@ -276,6 +276,16 @@ <title>GRANT on Database Objects</title>
     </varlistentry>
 
     <varlistentry>
+     <term>PUBLICATION</term>
+     <listitem>
+      <para>
+       Allows the use of the specified table in a publication.  (See the
+       <xref linkend="sql-createpublication"> statement.)
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
      <term>CREATE</term>
      <listitem>
       <para>
@@ -531,12 +541,13 @@ <title>Notes</title>
             D -- TRUNCATE
             x -- REFERENCES
             t -- TRIGGER
+            p -- PUBLICATION
             X -- EXECUTE
             U -- USAGE
             C -- CREATE
             c -- CONNECT
             T -- TEMPORARY
-      arwdDxt -- ALL PRIVILEGES (for tables, varies for other objects)
+     arwdDxtp -- ALL PRIVILEGES (for tables, varies for other objects)
             * -- grant option for preceding privilege
 
         /yyyy -- role that granted this privilege
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index c12f31a376..3e60c5476b 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -3249,6 +3249,8 @@ string_to_privilege(const char *privname)
 		return ACL_CREATE_TEMP;
 	if (strcmp(privname, "connect") == 0)
 		return ACL_CONNECT;
+	if (strcmp(privname, "publication") == 0)
+		return ACL_PUBLICATION;
 	if (strcmp(privname, "rule") == 0)
 		return 0;				/* ignore old RULE privileges */
 	ereport(ERROR,
@@ -3286,6 +3288,8 @@ privilege_to_string(AclMode privilege)
 			return "TEMP";
 		case ACL_CONNECT:
 			return "CONNECT";
+		case ACL_PUBLICATION:
+			return "PUBLICATION";
 		default:
 			elog(ERROR, "unrecognized privilege: %d", (int) privilege);
 	}
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index eb5436f72b..3e00414879 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -568,6 +568,8 @@ RemovePublicationRelById(Oid prid)
 /*
  * Gather all tables optinally filtered by schema name.
  * The gathered tables are locked in access share lock mode.
+ *
+ * TODO check table permissions/wait for code changes
  */
 static List *
 GatherTables(char *nspname)
@@ -651,9 +653,17 @@ GatherTableList(List *tables)
 		Relation	rel;
 		bool		recurse = interpretInhOption(rv->inhOpt);
 		Oid			myrelid;
+		AclResult	aclresult;
 
 		rel = heap_openrv(rv, AccessShareLock);
 		myrelid = RelationGetRelid(rel);
+
+		aclresult = pg_class_aclcheck(myrelid, GetUserId(), ACL_PUBLICATION);
+		if (aclresult != ACLCHECK_OK)
+			if (aclresult != ACLCHECK_OK)
+				aclcheck_error(aclresult, ACL_KIND_CLASS,
+							   RelationGetRelationName(rel));
+
 		/* don't throw error for "foo, foo" */
 		if (list_member_oid(relids, myrelid))
 		{
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 025a99e55a..5ebd86a061 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -314,6 +314,9 @@ aclparse(const char *s, AclItem *aip)
 			case ACL_CONNECT_CHR:
 				read = ACL_CONNECT;
 				break;
+			case ACL_PUBLICATION_CHR:
+				read = ACL_PUBLICATION;
+				break;
 			case 'R':			/* ignore old RULE privileges */
 				read = 0;
 				break;
@@ -1625,6 +1628,8 @@ convert_priv_string(text *priv_type_text)
 		return ACL_CREATE_TEMP;
 	if (pg_strcasecmp(priv_type, "CONNECT") == 0)
 		return ACL_CONNECT;
+	if (pg_strcasecmp(priv_type, "PUBLICATION") == 0)
+		return ACL_PUBLICATION;
 	if (pg_strcasecmp(priv_type, "RULE") == 0)
 		return 0;				/* ignore old RULE privileges */
 
@@ -1721,6 +1726,8 @@ convert_aclright_to_string(int aclright)
 			return "TEMPORARY";
 		case ACL_CONNECT:
 			return "CONNECT";
+		case ACL_PUBLICATION:
+			return "PUBLICATION";
 		default:
 			elog(ERROR, "unrecognized aclright: %d", aclright);
 			return NULL;
@@ -2032,6 +2039,8 @@ convert_table_priv_string(text *priv_type_text)
 		{"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
 		{"TRIGGER", ACL_TRIGGER},
 		{"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
+		{"PUBLICATION", ACL_PUBLICATION},
+		{"PUBLICATION WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_PUBLICATION)},
 		{"RULE", 0},			/* ignore old RULE privileges */
 		{"RULE WITH GRANT OPTION", 0},
 		{NULL, 0}
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index cd1e8c4a68..c668ec7494 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -492,6 +492,8 @@ do { \
 			CONVERT_PRIV('a', "INSERT");
 			if (remoteVersion >= 70200)
 				CONVERT_PRIV('x', "REFERENCES");
+			if (remoteVersion >= 100000)
+				CONVERT_PRIV('p', "PUBLICATION");
 			/* rest are not applicable to columns */
 			if (subname == NULL)
 			{
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index f017ee4721..260c48d364 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -73,7 +73,8 @@ typedef uint32 AclMode;			/* a bitmask of privilege bits */
 #define ACL_CREATE		(1<<9)	/* for namespaces and databases */
 #define ACL_CREATE_TEMP (1<<10) /* for databases */
 #define ACL_CONNECT		(1<<11) /* for databases */
-#define N_ACL_RIGHTS	12		/* 1 plus the last 1<<x */
+#define ACL_PUBLICATION	(1<<12)
+#define N_ACL_RIGHTS	13		/* 1 plus the last 1<<x */
 #define ACL_NO_RIGHTS	0
 /* Currently, SELECT ... FOR [KEY] UPDATE/SHARE requires UPDATE privileges */
 #define ACL_SELECT_FOR_UPDATE	ACL_UPDATE
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 6b25eb9101..8008cfef71 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -139,15 +139,16 @@ typedef ArrayType Acl;
 #define ACL_CREATE_CHR			'C'
 #define ACL_CREATE_TEMP_CHR		'T'
 #define ACL_CONNECT_CHR			'c'
+#define ACL_PUBLICATION_CHR		'p'
 
 /* string holding all privilege code chars, in order by bitmask position */
-#define ACL_ALL_RIGHTS_STR	"arwdDxtXUCTc"
+#define ACL_ALL_RIGHTS_STR	"arwdDxtXUCTcp"
 
 /*
  * Bitmasks defining "all rights" for each supported object type
  */
 #define ACL_ALL_RIGHTS_COLUMN		(ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_REFERENCES)
-#define ACL_ALL_RIGHTS_RELATION		(ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER)
+#define ACL_ALL_RIGHTS_RELATION		(ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER|ACL_PUBLICATION)
 #define ACL_ALL_RIGHTS_SEQUENCE		(ACL_USAGE|ACL_SELECT|ACL_UPDATE)
 #define ACL_ALL_RIGHTS_DATABASE		(ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
 #define ACL_ALL_RIGHTS_FDW			(ACL_USAGE)
diff --git a/src/test/regress/expected/dependency.out b/src/test/regress/expected/dependency.out
index 8e50f8ffbb..33b11c5732 100644
--- a/src/test/regress/expected/dependency.out
+++ b/src/test/regress/expected/dependency.out
@@ -19,7 +19,7 @@ DETAIL:  privileges for table deptest
 REVOKE SELECT ON deptest FROM GROUP regress_dep_group;
 DROP GROUP regress_dep_group;
 -- can't drop the user if we revoke the privileges partially
-REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES ON deptest FROM regress_dep_user;
+REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, PUBLICATION ON deptest FROM regress_dep_user;
 DROP USER regress_dep_user;
 ERROR:  role "regress_dep_user" cannot be dropped because some objects depend on it
 DETAIL:  privileges for table deptest
@@ -63,21 +63,21 @@ CREATE TABLE deptest (a serial primary key, b text);
 GRANT ALL ON deptest1 TO regress_dep_user2;
 RESET SESSION AUTHORIZATION;
 \z deptest1
-                                               Access privileges
- Schema |   Name   | Type  |                 Access privileges                  | Column privileges | Policies 
---------+----------+-------+----------------------------------------------------+-------------------+----------
- public | deptest1 | table | regress_dep_user0=arwdDxt/regress_dep_user0       +|                   | 
-        |          |       | regress_dep_user1=a*r*w*d*D*x*t*/regress_dep_user0+|                   | 
-        |          |       | regress_dep_user2=arwdDxt/regress_dep_user1        |                   | 
+                                                Access privileges
+ Schema |   Name   | Type  |                  Access privileges                   | Column privileges | Policies 
+--------+----------+-------+------------------------------------------------------+-------------------+----------
+ public | deptest1 | table | regress_dep_user0=arwdDxtp/regress_dep_user0        +|                   | 
+        |          |       | regress_dep_user1=a*r*w*d*D*x*t*p*/regress_dep_user0+|                   | 
+        |          |       | regress_dep_user2=arwdDxtp/regress_dep_user1         |                   | 
 (1 row)
 
 DROP OWNED BY regress_dep_user1;
 -- all grants revoked
 \z deptest1
-                                           Access privileges
- Schema |   Name   | Type  |              Access privileges              | Column privileges | Policies 
---------+----------+-------+---------------------------------------------+-------------------+----------
- public | deptest1 | table | regress_dep_user0=arwdDxt/regress_dep_user0 |                   | 
+                                            Access privileges
+ Schema |   Name   | Type  |              Access privileges               | Column privileges | Policies 
+--------+----------+-------+----------------------------------------------+-------------------+----------
+ public | deptest1 | table | regress_dep_user0=arwdDxtp/regress_dep_user0 |                   | 
 (1 row)
 
 -- table was dropped
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index f66b4432a1..fa47c3d0b3 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -1487,38 +1487,38 @@ set session role regress_user4;
 grant select on dep_priv_test to regress_user5;
 \dp dep_priv_test
                                           Access privileges
- Schema |     Name      | Type  |          Access privileges          | Column privileges | Policies 
---------+---------------+-------+-------------------------------------+-------------------+----------
- public | dep_priv_test | table | regress_user1=arwdDxt/regress_user1+|                   | 
-        |               |       | regress_user2=r*/regress_user1     +|                   | 
-        |               |       | regress_user3=r*/regress_user1     +|                   | 
-        |               |       | regress_user4=r*/regress_user2     +|                   | 
-        |               |       | regress_user4=r*/regress_user3     +|                   | 
-        |               |       | regress_user5=r/regress_user4       |                   | 
+ Schema |     Name      | Type  |          Access privileges           | Column privileges | Policies 
+--------+---------------+-------+--------------------------------------+-------------------+----------
+ public | dep_priv_test | table | regress_user1=arwdDxtp/regress_user1+|                   | 
+        |               |       | regress_user2=r*/regress_user1      +|                   | 
+        |               |       | regress_user3=r*/regress_user1      +|                   | 
+        |               |       | regress_user4=r*/regress_user2      +|                   | 
+        |               |       | regress_user4=r*/regress_user3      +|                   | 
+        |               |       | regress_user5=r/regress_user4        |                   | 
 (1 row)
 
 set session role regress_user2;
 revoke select on dep_priv_test from regress_user4 cascade;
 \dp dep_priv_test
                                           Access privileges
- Schema |     Name      | Type  |          Access privileges          | Column privileges | Policies 
---------+---------------+-------+-------------------------------------+-------------------+----------
- public | dep_priv_test | table | regress_user1=arwdDxt/regress_user1+|                   | 
-        |               |       | regress_user2=r*/regress_user1     +|                   | 
-        |               |       | regress_user3=r*/regress_user1     +|                   | 
-        |               |       | regress_user4=r*/regress_user3     +|                   | 
-        |               |       | regress_user5=r/regress_user4       |                   | 
+ Schema |     Name      | Type  |          Access privileges           | Column privileges | Policies 
+--------+---------------+-------+--------------------------------------+-------------------+----------
+ public | dep_priv_test | table | regress_user1=arwdDxtp/regress_user1+|                   | 
+        |               |       | regress_user2=r*/regress_user1      +|                   | 
+        |               |       | regress_user3=r*/regress_user1      +|                   | 
+        |               |       | regress_user4=r*/regress_user3      +|                   | 
+        |               |       | regress_user5=r/regress_user4        |                   | 
 (1 row)
 
 set session role regress_user3;
 revoke select on dep_priv_test from regress_user4 cascade;
 \dp dep_priv_test
                                           Access privileges
- Schema |     Name      | Type  |          Access privileges          | Column privileges | Policies 
---------+---------------+-------+-------------------------------------+-------------------+----------
- public | dep_priv_test | table | regress_user1=arwdDxt/regress_user1+|                   | 
-        |               |       | regress_user2=r*/regress_user1     +|                   | 
-        |               |       | regress_user3=r*/regress_user1      |                   | 
+ Schema |     Name      | Type  |          Access privileges           | Column privileges | Policies 
+--------+---------------+-------+--------------------------------------+-------------------+----------
+ public | dep_priv_test | table | regress_user1=arwdDxtp/regress_user1+|                   | 
+        |               |       | regress_user2=r*/regress_user1      +|                   | 
+        |               |       | regress_user3=r*/regress_user1       |                   | 
 (1 row)
 
 set session role regress_user1;
diff --git a/src/test/regress/sql/dependency.sql b/src/test/regress/sql/dependency.sql
index f5c45e4666..2bdd51532c 100644
--- a/src/test/regress/sql/dependency.sql
+++ b/src/test/regress/sql/dependency.sql
@@ -21,7 +21,7 @@ CREATE TABLE deptest (f1 serial primary key, f2 text);
 DROP GROUP regress_dep_group;
 
 -- can't drop the user if we revoke the privileges partially
-REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES ON deptest FROM regress_dep_user;
+REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, PUBLICATION ON deptest FROM regress_dep_user;
 DROP USER regress_dep_user;
 
 -- now we are OK to drop him
-- 
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