0004-DDL-replication-for-index-DDL-commands-2023_04_04.patch

application/octet-stream

Filename: 0004-DDL-replication-for-index-DDL-commands-2023_04_04.patch
Type: application/octet-stream
Part: 5
Message: RE: Support logical replication of DDLs

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch 0004
Subject: DDL replication for index DDL commands
File+
contrib/test_decoding/test_decoding.c 2 3
src/backend/catalog/pg_publication.c 1 0
src/backend/commands/publicationcmds.c 34 10
src/backend/replication/logical/ddltrigger.c 12 1
src/backend/replication/logical/logical.c 16 16
src/backend/replication/pgoutput/pgoutput.c 72 2
src/backend/utils/cache/relcache.c 1 0
src/bin/pg_dump/pg_dump.c 26 5
src/bin/pg_dump/pg_dump.h 1 0
src/bin/psql/describe.c 9 4
src/include/catalog/pg_publication.h 4 0
src/include/replication/ddlmessage.h 2 1
src/test/regress/expected/psql.out 3 3
src/test/regress/expected/publication.out 66 66
From 0ca3edaf659bb41df24af15fdf1e503fcc53bf86 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <houzj.fnst@cn.fujitsu.com>
Date: Tue, 4 Apr 2023 09:52:08 +0800
Subject: [PATCH 4/6] DDL replication for index DDL commands

---
 contrib/test_decoding/test_decoding.c        |   5 +-
 src/backend/catalog/pg_publication.c         |   1 +
 src/backend/commands/publicationcmds.c       |  44 +++++--
 src/backend/replication/logical/ddltrigger.c |  13 +-
 src/backend/replication/logical/logical.c    |  32 ++---
 src/backend/replication/pgoutput/pgoutput.c  |  74 ++++++++++-
 src/backend/utils/cache/relcache.c           |   1 +
 src/bin/pg_dump/pg_dump.c                    |  31 ++++-
 src/bin/pg_dump/pg_dump.h                    |   1 +
 src/bin/psql/describe.c                      |  13 +-
 src/include/catalog/pg_publication.h         |   4 +
 src/include/replication/ddlmessage.h         |   3 +-
 src/test/regress/expected/psql.out           |   6 +-
 src/test/regress/expected/publication.out    | 132 +++++++++----------
 14 files changed, 249 insertions(+), 111 deletions(-)

diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c
index 763d5c007f..da5b41df59 100644
--- a/contrib/test_decoding/test_decoding.c
+++ b/contrib/test_decoding/test_decoding.c
@@ -774,9 +774,11 @@ pg_decode_ddl_message(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 		appendStringInfo(ctx->out, "cmdtype: Simple, ");
 		break;
 	case DCT_TableDropStart:
+	case DCT_ObjectDropStart:
 		appendStringInfo(ctx->out, "cmdtype: Drop start, ");
 		break;
 	case DCT_TableDropEnd:
+	case DCT_ObjectDropEnd:
 		appendStringInfo(ctx->out, "cmdtype: Drop end, ");
 		break;
 	case DCT_TableAlter:
@@ -785,9 +787,6 @@ pg_decode_ddl_message(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 	case DCT_ObjectCreate:
 		appendStringInfo(ctx->out, "cmdtype: Create, ");
 		break;
-	case DCT_ObjectDrop:
-		appendStringInfo(ctx->out, "cmdtype: Drop, ");
-		break;
 	default:
 		appendStringInfo(ctx->out, "cmdtype: Invalid, ");
 		break;
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index d209602e28..1a3105e025 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -1029,6 +1029,7 @@ GetPublication(Oid pubid)
 	pub->pubactions.pubdelete = pubform->pubdelete;
 	pub->pubactions.pubtruncate = pubform->pubtruncate;
 	pub->pubactions.pubddl_table = pubform->pubddl_table;
+	pub->pubactions.pubddl_index = pubform->pubddl_index;
 	pub->pubviaroot = pubform->pubviaroot;
 
 	ReleaseSysCache(tup);
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 67f1bcec5c..0abed0082f 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -103,6 +103,7 @@ parse_publication_options(ParseState *pstate,
 	pubactions->pubdelete = true;
 	pubactions->pubtruncate = true;
 	pubactions->pubddl_table = false;
+	pubactions->pubddl_index = false;
 	*publish_via_partition_root = false;
 
 	/* Parse options */
@@ -178,6 +179,7 @@ parse_publication_options(ParseState *pstate,
 			 * should be published.
 			 */
 			pubactions->pubddl_table = false;
+			pubactions->pubddl_index = false;
 
 			*ddl_type_given = true;
 			ddl_level = defGetString(defel);
@@ -194,6 +196,8 @@ parse_publication_options(ParseState *pstate,
 
 				if (strcmp(publish_opt, "table") == 0)
 					pubactions->pubddl_table = true;
+				else if (strcmp(publish_opt, "index") == 0)
+					pubactions->pubddl_index = true;
 				else
 					ereport(ERROR,
 							errcode(ERRCODE_SYNTAX_ERROR),
@@ -849,6 +853,10 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
 	AclResult	aclresult;
 	List	   *relations = NIL;
 	List	   *schemaidlist = NIL;
+	List	   *start_commands = NIL;
+	List	   *rewrite_commands = NIL;
+	List	   *init_commands = NIL;
+	List	   *end_commands = NIL;
 
 	/* must have CREATE privilege on database */
 	aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(), ACL_CREATE);
@@ -904,6 +912,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
 		BoolGetDatum(pubactions.pubtruncate);
 	values[Anum_pg_publication_pubddl_table - 1] =
 	BoolGetDatum(pubactions.pubddl_table);
+	values[Anum_pg_publication_pubddl_index - 1] =
+	BoolGetDatum(pubactions.pubddl_index);
 	values[Anum_pg_publication_pubviaroot - 1] =
 		BoolGetDatum(publish_via_partition_root);
 
@@ -941,7 +951,7 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
 		{
 			List	   *rels;
 
-			if (pubactions.pubddl_table)
+			if (pubactions.pubddl_table || pubactions.pubddl_index)
 				ereport(ERROR,
 						errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 						errmsg("cannot add table to publication \"%s\" if DDL replication is enabled",
@@ -972,20 +982,31 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
 
 	/*
 	 * Create an event trigger to allow logging of DDL statements.
-	 *
 	 */
 	if (pubactions.pubddl_table)
 	{
-		List	   *start_commands = list_make1_int(CMDTAG_DROP_TABLE);
-		List	   *rewrite_commands = list_make1_int(CMDTAG_ALTER_TABLE);
-		List	   *init_commands = list_make2_int(CMDTAG_CREATE_TABLE_AS,
-												   CMDTAG_SELECT_INTO);
-		List	   *end_commands = NIL;
+		start_commands = lappend_int(start_commands, CMDTAG_DROP_TABLE);
+		rewrite_commands = lappend_int(rewrite_commands, CMDTAG_ALTER_TABLE);
+
+		init_commands = lappend_int(init_commands, CMDTAG_CREATE_TABLE_AS);
+		init_commands = lappend_int(init_commands, CMDTAG_SELECT_INTO);
 
 		end_commands = lappend_int(end_commands, CMDTAG_CREATE_TABLE);
 		end_commands = lappend_int(end_commands, CMDTAG_ALTER_TABLE);
 		end_commands = lappend_int(end_commands, CMDTAG_DROP_TABLE);
+	}
+
+	if (pubactions.pubddl_index)
+	{
+		start_commands = lappend_int(start_commands, CMDTAG_DROP_INDEX);
 
+		end_commands = lappend_int(end_commands, CMDTAG_CREATE_INDEX);
+		end_commands = lappend_int(end_commands, CMDTAG_ALTER_INDEX);
+		end_commands = lappend_int(end_commands, CMDTAG_DROP_INDEX);
+	}
+
+	if (pubactions.pubddl_table || pubactions.pubddl_index)
+	{
 		/* Create the ddl_command_end event trigger */
 		CreateDDLReplicaEventTrigger(PUB_TRIG_EVENT1, end_commands,
 									 myself, puboid);
@@ -1128,7 +1149,7 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
 		}
 	}
 
-	if (ddl_type_given && pubactions.pubddl_table)
+	if (ddl_type_given && (pubactions.pubddl_table || pubactions.pubddl_index))
 	{
 		if (root_relids == NIL)
 			root_relids = GetPublicationRelations(pubform->oid,
@@ -1161,6 +1182,9 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
 
 		values[Anum_pg_publication_pubddl_table - 1] = BoolGetDatum(pubactions.pubddl_table);
 		replaces[Anum_pg_publication_pubddl_table - 1] = true;
+
+		values[Anum_pg_publication_pubddl_index - 1] = BoolGetDatum(pubactions.pubddl_index);
+		replaces[Anum_pg_publication_pubddl_index - 1] = true;
 	}
 
 	if (publish_via_partition_root_given)
@@ -1268,7 +1292,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
 
 	if (stmt->action == AP_AddObjects)
 	{
-		if (pubform->pubddl_table)
+		if (pubform->pubddl_table || pubform->pubddl_index)
 			ereport(ERROR,
 					errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					errmsg("cannot add table to publication \"%s\" if DDL replication is enabled",
@@ -1292,7 +1316,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
 		List	   *delrels = NIL;
 		ListCell   *oldlc;
 
-		if (pubform->pubddl_table)
+		if (pubform->pubddl_table || pubform->pubddl_index)
 			ereport(ERROR,
 					errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					errmsg("cannot add table to publication \"%s\" if DDL replication is enabled",
diff --git a/src/backend/replication/logical/ddltrigger.c b/src/backend/replication/logical/ddltrigger.c
index 1282340c2b..fb35cc2c7f 100644
--- a/src/backend/replication/logical/ddltrigger.c
+++ b/src/backend/replication/logical/ddltrigger.c
@@ -81,8 +81,17 @@ publication_deparse_ddl_command_start(PG_FUNCTION_ARGS)
 		 * new table.
 		 */
 		if (relpersist == RELPERSISTENCE_PERMANENT)
-			LogLogicalDDLMessage("deparse", address.objectId, DCT_TableDropStart,
+		{
+			DeparsedCommandType cmdtype;
+
+			if (stmt->removeType == OBJECT_TABLE)
+				cmdtype = DCT_TableDropStart;
+			else
+				cmdtype = DCT_ObjectDropStart;
+
+			LogLogicalDDLMessage("deparse", address.objectId, cmdtype,
 								 command, strlen(command) + 1);
+		}
 
 		if (relation)
 			table_close(relation, NoLock);
@@ -225,6 +234,8 @@ publication_deparse_ddl_command_end(PG_FUNCTION_ARGS)
 
 		if (strcmp(obj->objecttype, "table") == 0)
 			cmdtype = DCT_TableDropEnd;
+		else if (strcmp(obj->objecttype, "index") == 0)
+			cmdtype = DCT_ObjectDropEnd;
 		else
 			continue;
 
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index f56a716567..533e27fb07 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -75,9 +75,9 @@ static void message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 							   XLogRecPtr message_lsn, bool transactional,
 							   const char *prefix, Size message_size, const char *message);
 static void ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
-								  XLogRecPtr message_lsn, const char *prefix,
-								  Oid relid, DeparsedCommandType cmdtype,
-								  Size message_size, const char *message);
+						   XLogRecPtr message_lsn, const char *prefix,
+						   Oid relid, DeparsedCommandType cmdtype,
+						   Size message_size, const char *message);
 
 /* streaming callbacks */
 static void stream_start_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
@@ -96,10 +96,10 @@ static void stream_message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *tx
 									  XLogRecPtr message_lsn, bool transactional,
 									  const char *prefix, Size message_size, const char *message);
 static void stream_ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
-										 XLogRecPtr message_lsn,
-										 const char *prefix,
-										 Oid relid, DeparsedCommandType cmdtype,
-										 Size message_size, const char *message);
+								  XLogRecPtr message_lsn,
+								  const char *prefix,
+								  Oid relid, DeparsedCommandType cmdtype,
+								  Size message_size, const char *message);
 static void stream_truncate_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 									   int nrelations, Relation relations[], ReorderBufferChange *change);
 
@@ -1248,10 +1248,10 @@ message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 
 static void
 ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
-					  XLogRecPtr message_lsn,
-					  const char *prefix, Oid relid, DeparsedCommandType cmdtype,
-					  Size message_size,
-					  const char *message)
+			   XLogRecPtr message_lsn,
+			   const char *prefix, Oid relid, DeparsedCommandType cmdtype,
+			   Size message_size,
+			   const char *message)
 {
 	LogicalDecodingContext *ctx = cache->private_data;
 	LogicalErrorCallbackState state;
@@ -1278,7 +1278,7 @@ ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 
 	/* do the actual work: call callback */
 	ctx->callbacks.ddl_cb(ctx, txn, message_lsn, prefix, relid, cmdtype,
-								 message_size, message);
+						  message_size, message);
 
 	/* Pop the error context stack */
 	error_context_stack = errcallback.previous;
@@ -1601,10 +1601,10 @@ stream_message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 
 static void
 stream_ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
-							 XLogRecPtr message_lsn,
-							 const char *prefix, Oid relid, DeparsedCommandType cmdtype,
-							 Size message_size,
-							 const char *message)
+					  XLogRecPtr message_lsn,
+					  const char *prefix, Oid relid, DeparsedCommandType cmdtype,
+					  Size message_size,
+					  const char *message)
 {
 	LogicalDecodingContext *ctx = cache->private_data;
 	LogicalErrorCallbackState state;
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 7ea9ff51ec..429a3aef91 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -219,10 +219,20 @@ typedef struct PGOutputTxnData
 /* Map used to remember which relation schemas we sent. */
 static HTAB *RelationSyncCache = NULL;
 
+/* Struct to cache the published DDL. */
+typedef struct DDLSyncCache
+{
+	bool		valid;
+	bool		pubindex;
+} DDLSyncCache;
+
+static DDLSyncCache *ddlcache = NULL;
+
 static void init_rel_sync_cache(MemoryContext cachectx);
 static void cleanup_rel_sync_cache(TransactionId xid, bool is_commit);
 static RelationSyncEntry *get_rel_sync_entry(PGOutputData *data,
 											 Relation relation);
+static void build_ddl_sync_cache(PGOutputData *data);
 static void rel_sync_cache_relation_cb(Datum arg, Oid relid);
 static void rel_sync_cache_publication_cb(Datum arg, int cacheid,
 										  uint32 hashvalue);
@@ -1760,6 +1770,27 @@ is_object_published(LogicalDecodingContext *ctx, Oid objid)
 				relentry->publish_as_relid != objid)
 				return false;
 
+			break;
+		case RELKIND_INDEX:
+			build_ddl_sync_cache(data);
+
+			if (!ddlcache->pubindex)
+				return false;
+
+			/* Get the table OID that the index is for. */
+			relation = RelationIdGetRelation(objid);
+			objid = relation->rd_index->indrelid;
+			RelationClose(relation);
+
+			/* Filter the index DDLs if the index's table was not published. */
+			relation = RelationIdGetRelation(objid);
+			relentry = get_rel_sync_entry(data, relation);
+			RelationClose(relation);
+
+			if (!relentry->pubactions.pubddl_table ||
+				relentry->publish_as_relid != objid)
+				return false;
+
 			break;
 		default:
 			/* unsupported objects */
@@ -1785,12 +1816,14 @@ pgoutput_ddl(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 	 * we cannot get the required information from the catalog, so we skip the
 	 * check for them.
 	 */
-	if (cmdtype != DCT_TableDropEnd && !is_object_published(ctx, relid))
+	if (cmdtype != DCT_TableDropEnd && cmdtype != DCT_ObjectDropEnd &&
+		!is_object_published(ctx, relid))
 		return;
 
 	switch (cmdtype)
 	{
 		case DCT_TableDropStart:
+		case DCT_ObjectDropStart:
 			{
 				MemoryContext	old;
 
@@ -1814,6 +1847,7 @@ pgoutput_ddl(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 			return;
 
 		case DCT_TableDropEnd:
+		case DCT_ObjectDropEnd:
 			if (!list_member_oid(txndata->deleted_relids, relid))
 				return;
 
@@ -2203,7 +2237,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
 		entry->streamed_txns = NIL;
 		entry->pubactions.pubinsert = entry->pubactions.pubupdate =
 			entry->pubactions.pubdelete = entry->pubactions.pubtruncate =
-			entry->pubactions.pubddl_table = false;
+			entry->pubactions.pubddl_table = entry->pubactions.pubddl_index = false;
 		entry->new_slot = NULL;
 		entry->old_slot = NULL;
 		memset(entry->exprstate, 0, sizeof(entry->exprstate));
@@ -2250,6 +2284,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
 		entry->pubactions.pubdelete = false;
 		entry->pubactions.pubtruncate = false;
 		entry->pubactions.pubddl_table = false;
+		entry->pubactions.pubddl_index = false;
 
 		/*
 		 * Tuple slots cleanups. (Will be rebuilt later if needed).
@@ -2364,6 +2399,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
 				entry->pubactions.pubdelete |= pub->pubactions.pubdelete;
 				entry->pubactions.pubtruncate |= pub->pubactions.pubtruncate;
 				entry->pubactions.pubddl_table |= pub->pubactions.pubddl_table;
+				entry->pubactions.pubddl_index |= pub->pubactions.pubddl_index;
 
 				/*
 				 * We want to publish the changes as the top-most ancestor
@@ -2428,6 +2464,40 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
 	return entry;
 }
 
+/*
+ * This looks up all publications and build the cache about which DDLs to
+ * publish.
+ */
+static void
+build_ddl_sync_cache(PGOutputData *data)
+{
+	ListCell	 *lc;
+	MemoryContext oldctx;
+
+	if (ddlcache == NULL)
+	{
+		oldctx = MemoryContextSwitchTo(CacheMemoryContext);
+		ddlcache = (DDLSyncCache *) palloc0(sizeof(DDLSyncCache));
+		MemoryContextSwitchTo(oldctx);
+	}
+
+	if (ddlcache->valid)
+		return;
+
+	reload_publications(data);
+
+	foreach(lc, data->publications)
+	{
+		Publication *pub = lfirst(lc);
+
+		ddlcache->pubindex |= pub->pubactions.pubddl_index;
+	}
+
+	ddlcache->valid = true;
+
+	return;
+}
+
 /*
  * Cleanup list of streamed transactions and update the schema_sent flag.
  *
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 9198da2eb1..12259c9dd8 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5721,6 +5721,7 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
 		pubdesc->pubactions.pubdelete |= pubform->pubdelete;
 		pubdesc->pubactions.pubtruncate |= pubform->pubtruncate;
 		pubdesc->pubactions.pubddl_table |= pubform->pubddl_table;
+		pubdesc->pubactions.pubddl_index |= pubform->pubddl_index;
 
 		/*
 		 * Check if all columns referenced in the filter expression are part
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 526987418c..34cedc0432 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -4065,6 +4065,7 @@ getPublications(Archive *fout, int *numPublications)
 	int			i_pubdelete;
 	int			i_pubtruncate;
 	int			i_pubddl_table;
+	int			i_pubddl_index;
 	int			i_pubviaroot;
 	int			i,
 				ntups;
@@ -4084,25 +4085,25 @@ getPublications(Archive *fout, int *numPublications)
 		appendPQExpBufferStr(query,
 							 "SELECT p.tableoid, p.oid, p.pubname, "
 							 "p.pubowner, "
-							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubddl_table, p.pubviaroot "
+							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubddl_table, p.pubddl_index, p.pubviaroot "
 							 "FROM pg_publication p");
 	else if (fout->remoteVersion >= 130000)
 		appendPQExpBufferStr(query,
 							 "SELECT p.tableoid, p.oid, p.pubname, "
 							 "p.pubowner, "
-							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubddl_table, p.pubviaroot "
+							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubddl_table, false as p.pubddl_index, p.pubviaroot "
 							 "FROM pg_publication p");
 	else if (fout->remoteVersion >= 110000)
 		appendPQExpBufferStr(query,
 							 "SELECT p.tableoid, p.oid, p.pubname, "
 							 "p.pubowner, "
-							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubddl_table, false AS pubviaroot "
+							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubddl_table, false as p.pubddl_index, false AS pubviaroot "
 							 "FROM pg_publication p");
 	else
 		appendPQExpBufferStr(query,
 							 "SELECT p.tableoid, p.oid, p.pubname, "
 							 "p.pubowner, "
-							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false as p.pubddl_table, false AS pubviaroot "
+							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false as p.pubddl_table, false as p.pubddl_index, false AS pubviaroot "
 							 "FROM pg_publication p");
 
 	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -4119,6 +4120,7 @@ getPublications(Archive *fout, int *numPublications)
 	i_pubdelete = PQfnumber(res, "pubdelete");
 	i_pubtruncate = PQfnumber(res, "pubtruncate");
 	i_pubddl_table = PQfnumber(res, "pubddl_table");
+	i_pubddl_index = PQfnumber(res, "pubddl_index");
 	i_pubviaroot = PQfnumber(res, "pubviaroot");
 
 	pubinfo = pg_malloc(ntups * sizeof(PublicationInfo));
@@ -4144,6 +4146,8 @@ getPublications(Archive *fout, int *numPublications)
 			(strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0);
 		pubinfo[i].pubddl_table =
 			(strcmp(PQgetvalue(res, i, i_pubddl_table), "t") == 0);
+		pubinfo[i].pubddl_index =
+			(strcmp(PQgetvalue(res, i, i_pubddl_index), "t") == 0);
 		pubinfo[i].pubviaroot =
 			(strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0);
 
@@ -4225,8 +4229,25 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo)
 
 	appendPQExpBufferStr(query, "'");
 
+	first = true;
+	appendPQExpBufferStr(query, ", ddl = '");
+
 	if (pubinfo->pubddl_table)
-		appendPQExpBufferStr(query, ", ddl = 'table'");
+	{
+		appendPQExpBufferStr(query, "table");
+		first = false;
+	}
+
+	if (pubinfo->pubddl_index)
+	{
+		if (!first)
+			appendPQExpBufferStr(query, ", ");
+
+		appendPQExpBufferStr(query, "index");
+		first = false;
+	}
+
+	appendPQExpBufferStr(query, "'");
 
 	if (pubinfo->pubviaroot)
 		appendPQExpBufferStr(query, ", publish_via_partition_root = true");
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index bd5f8fb669..9ae6a38e00 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -621,6 +621,7 @@ typedef struct _PublicationInfo
 	bool		pubdelete;
 	bool		pubtruncate;
 	bool		pubddl_table;
+	bool		pubddl_index;
 	bool		pubviaroot;
 } PublicationInfo;
 
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index a41500deed..fb3eb67e98 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -6183,7 +6183,7 @@ listPublications(const char *pattern)
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
-	static const bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
+	static const bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false, false};
 
 	if (pset.sversion < 100000)
 	{
@@ -6205,9 +6205,13 @@ listPublications(const char *pattern)
 					  gettext_noop("Owner"),
 					  gettext_noop("All tables"));
 	if (pset.sversion >= 160000)
+	{
 		appendPQExpBuffer(&buf,
-						  ",\n  pubddl_table AS \"%s\"",
-						  gettext_noop("Table DDLs"));
+						  ",\n  pubddl_table AS \"%s\",\n"
+						  "  pubddl_index AS \"%s\"\n",
+						  gettext_noop("Table DDLs"),
+						  gettext_noop("Index DDLs"));
+	}
 	appendPQExpBuffer(&buf,
 					  ",\n  pubinsert AS \"%s\",\n"
 					  "  pubupdate AS \"%s\",\n"
@@ -6339,7 +6343,8 @@ describePublications(const char *pattern)
 					  "  puballtables");
 	if (has_pubddl)
 		appendPQExpBufferStr(&buf,
-							 ", pubddl_table");
+							 ", pubddl_table, pubddl_index");
+
 	appendPQExpBufferStr(&buf,
 						 ",  pubinsert, pubupdate, pubdelete");
 	if (has_pubtruncate)
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index 74b28d7350..467731c61a 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -66,6 +66,9 @@ CATALOG(pg_publication,6104,PublicationRelationId)
 
 	/* true if table ddls are published */
 	bool		pubddl_table;
+
+	/* true if index ddls are published */
+	bool		pubddl_index;
 } FormData_pg_publication;
 
 /* ----------------
@@ -85,6 +88,7 @@ typedef struct PublicationActions
 	bool		pubdelete;
 	bool		pubtruncate;
 	bool		pubddl_table;
+	bool		pubddl_index;
 } PublicationActions;
 
 typedef struct PublicationDesc
diff --git a/src/include/replication/ddlmessage.h b/src/include/replication/ddlmessage.h
index 77df6ea11a..1a4aca8dd5 100644
--- a/src/include/replication/ddlmessage.h
+++ b/src/include/replication/ddlmessage.h
@@ -26,7 +26,8 @@ typedef enum DeparsedCommandType
 	DCT_TableDropEnd,
 	DCT_TableAlter,
 	DCT_ObjectCreate,
-	DCT_ObjectDrop
+	DCT_ObjectDropStart,
+	DCT_ObjectDropEnd
 } DeparsedCommandType;
 
 /*
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 1c6f33095c..3e6d2791c8 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -6223,9 +6223,9 @@ List of schemas
 (0 rows)
 
 \dRp "no.such.publication"
-                                    List of publications
- Name | Owner | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
-------+-------+------------+------------+---------+---------+---------+-----------+----------
+                                           List of publications
+ Name | Owner | All tables | Table DDLs | Index DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+------+-------+------------+------------+------------+---------+---------+---------+-----------+----------
 (0 rows)
 
 \dRs "no.such.subscription"
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 7d86977b29..6660f41674 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -30,20 +30,20 @@ ERROR:  conflicting or redundant options
 LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
                                                              ^
 \dRp
-                                                     List of publications
-        Name        |          Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
---------------------+--------------------------+------------+------------+---------+---------+---------+-----------+----------
- testpib_ins_trunct | regress_publication_user | f          | f          | t       | f       | f       | f         | f
- testpub_default    | regress_publication_user | f          | f          | f       | t       | f       | f         | f
+                                                           List of publications
+        Name        |          Owner           | All tables | Table DDLs | Index DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------+--------------------------+------------+------------+------------+---------+---------+---------+-----------+----------
+ testpib_ins_trunct | regress_publication_user | f          | f          | f          | t       | f       | f       | f         | f
+ testpub_default    | regress_publication_user | f          | f          | f          | f       | t       | f       | f         | f
 (2 rows)
 
 ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete');
 \dRp
-                                                     List of publications
-        Name        |          Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
---------------------+--------------------------+------------+------------+---------+---------+---------+-----------+----------
- testpib_ins_trunct | regress_publication_user | f          | f          | t       | f       | f       | f         | f
- testpub_default    | regress_publication_user | f          | f          | t       | t       | t       | f         | f
+                                                           List of publications
+        Name        |          Owner           | All tables | Table DDLs | Index DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------+--------------------------+------------+------------+------------+---------+---------+---------+-----------+----------
+ testpib_ins_trunct | regress_publication_user | f          | f          | f          | t       | f       | f       | f         | f
+ testpub_default    | regress_publication_user | f          | f          | f          | t       | t       | t       | f         | f
 (2 rows)
 
 --- adding tables
@@ -90,7 +90,7 @@ ALTER PUBLICATION testpub_fortable ADD TABLES IN SCHEMA pub_test;
                                       Publication testpub_fortable
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "public.testpub_tbl1"
 Tables from schemas:
@@ -102,7 +102,7 @@ ALTER PUBLICATION testpub_fortable DROP TABLES IN SCHEMA pub_test;
                                       Publication testpub_fortable
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "public.testpub_tbl1"
 
@@ -112,7 +112,7 @@ ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test;
                                       Publication testpub_fortable
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test"
 
@@ -126,7 +126,7 @@ RESET client_min_messages;
                                    Publication testpub_for_tbl_schema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "pub_test.testpub_nopk"
 Tables from schemas:
@@ -138,7 +138,7 @@ ALTER PUBLICATION testpub_forschema ADD TABLE pub_test.testpub_nopk;
                                       Publication testpub_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "pub_test.testpub_nopk"
 Tables from schemas:
@@ -150,7 +150,7 @@ ALTER PUBLICATION testpub_forschema DROP TABLE pub_test.testpub_nopk;
                                       Publication testpub_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test"
 
@@ -164,7 +164,7 @@ ALTER PUBLICATION testpub_forschema SET TABLE pub_test.testpub_nopk;
                                       Publication testpub_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "pub_test.testpub_nopk"
 
@@ -189,7 +189,7 @@ Publications:
                                     Publication testpub_foralltables
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | t          | f          | t       | t       | f       | f         | f
+ regress_publication_user | t          | f          | f       | t       | t       | f         | f
 (1 row)
 
 DROP TABLE testpub_tbl2;
@@ -204,7 +204,7 @@ RESET client_min_messages;
                                           Publication testpub3
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "public.testpub_tbl3"
     "public.testpub_tbl3a"
@@ -213,7 +213,7 @@ Tables:
                                           Publication testpub4
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "public.testpub_tbl3"
 
@@ -237,7 +237,7 @@ ALTER PUBLICATION testpub_forparted ADD TABLE testpub_parted;
                                       Publication testpub_forparted
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "public.testpub_parted"
 
@@ -255,7 +255,7 @@ ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true);
                                       Publication testpub_forparted
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | t
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "public.testpub_parted"
 
@@ -287,7 +287,7 @@ RESET client_min_messages;
                                           Publication testpub5
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | f       | f       | f         | f
+ regress_publication_user | f          | f          | f       | t       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5))
@@ -303,7 +303,7 @@ ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl3 WHERE (e > 1000 AND e < 200
                                           Publication testpub5
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | f       | f       | f         | f
+ regress_publication_user | f          | f          | f       | t       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5))
@@ -322,7 +322,7 @@ ALTER PUBLICATION testpub5 DROP TABLE testpub_rf_tbl2;
                                           Publication testpub5
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | f       | f       | f         | f
+ regress_publication_user | f          | f          | f       | t       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "public.testpub_rf_tbl3" WHERE ((e > 1000) AND (e < 2000))
@@ -333,7 +333,7 @@ ALTER PUBLICATION testpub5 SET TABLE testpub_rf_tbl3 WHERE (e > 300 AND e < 500)
                                           Publication testpub5
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | f       | f       | f         | f
+ regress_publication_user | f          | f          | f       | t       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl3" WHERE ((e > 300) AND (e < 500))
 
@@ -369,7 +369,7 @@ RESET client_min_messages;
                                        Publication testpub_syntax1
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | f       | f       | f         | f
+ regress_publication_user | f          | f          | f       | t       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "public.testpub_rf_tbl3" WHERE (e < 999)
@@ -382,7 +382,7 @@ RESET client_min_messages;
                                        Publication testpub_syntax2
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | f       | f       | f         | f
+ regress_publication_user | f          | f          | f       | t       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "testpub_rf_schema1.testpub_rf_tbl5" WHERE (h < 999)
@@ -500,7 +500,7 @@ RESET client_min_messages;
                                           Publication testpub6
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "testpub_rf_schema2.testpub_rf_tbl6" WHERE (i < 99)
 Tables from schemas:
@@ -717,7 +717,7 @@ ALTER PUBLICATION testpub_table_ins ADD TABLE testpub_tbl5 (a);		-- ok
                                       Publication testpub_table_ins
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | f       | f       | t         | f
+ regress_publication_user | f          | f          | f       | t       | f       | f         | t
 Tables:
     "public.testpub_tbl5" (a)
 
@@ -894,7 +894,7 @@ ALTER PUBLICATION testpub_both_filters ADD TABLE testpub_tbl_both_filters (a,c)
                                     Publication testpub_both_filters
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "public.testpub_tbl_both_filters" (a, c) WHERE (c <> 1)
 
@@ -1102,7 +1102,7 @@ ERROR:  publication "testpub_fortbl" already exists
                                        Publication testpub_fortbl
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "pub_test.testpub_nopk"
     "public.testpub_tbl1"
@@ -1143,7 +1143,7 @@ Publications:
                                        Publication testpub_default
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | f         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | f
 Tables:
     "pub_test.testpub_nopk"
     "public.testpub_tbl1"
@@ -1224,7 +1224,7 @@ DROP TABLE testpub_tbl1;
                                        Publication testpub_default
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | f         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | f
 (1 row)
 
 -- fail - must be owner of publication
@@ -1234,20 +1234,20 @@ ERROR:  must be owner of publication testpub_default
 RESET ROLE;
 ALTER PUBLICATION testpub_default RENAME TO testpub_foo;
 \dRp testpub_foo
-                                                 List of publications
-    Name     |          Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
--------------+--------------------------+------------+------------+---------+---------+---------+-----------+----------
- testpub_foo | regress_publication_user | f          | f          | t       | t       | t       | f         | f
+                                                        List of publications
+    Name     |          Owner           | All tables | Table DDLs | Index DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+-------------+--------------------------+------------+------------+------------+---------+---------+---------+-----------+----------
+ testpub_foo | regress_publication_user | f          | f          | f          | t       | t       | t       | f         | f
 (1 row)
 
 -- rename back to keep the rest simple
 ALTER PUBLICATION testpub_foo RENAME TO testpub_default;
 ALTER PUBLICATION testpub_default OWNER TO regress_publication_user2;
 \dRp testpub_default
-                                                    List of publications
-      Name       |           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
------------------+---------------------------+------------+------------+---------+---------+---------+-----------+----------
- testpub_default | regress_publication_user2 | f          | f          | t       | t       | t       | f         | f
+                                                          List of publications
+      Name       |           Owner           | All tables | Table DDLs | Index DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+-----------------+---------------------------+------------+------------+------------+---------+---------+---------+-----------+----------
+ testpub_default | regress_publication_user2 | f          | f          | f          | t       | t       | t       | f         | f
 (1 row)
 
 -- adding schemas and tables
@@ -1266,7 +1266,7 @@ CREATE PUBLICATION testpub1_forschema FOR TABLES IN SCHEMA pub_test1;
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
 
@@ -1275,7 +1275,7 @@ CREATE PUBLICATION testpub2_forschema FOR TABLES IN SCHEMA pub_test1, pub_test2,
                                      Publication testpub2_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1292,7 +1292,7 @@ RESET client_min_messages;
                                      Publication testpub3_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "public"
 
@@ -1300,7 +1300,7 @@ Tables from schemas:
                                      Publication testpub4_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "CURRENT_SCHEMA"
 
@@ -1308,7 +1308,7 @@ Tables from schemas:
                                      Publication testpub5_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "CURRENT_SCHEMA"
     "public"
@@ -1317,7 +1317,7 @@ Tables from schemas:
                                      Publication testpub6_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "CURRENT_SCHEMA"
     "public"
@@ -1326,7 +1326,7 @@ Tables from schemas:
                                       Publication testpub_fortable
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "CURRENT_SCHEMA.CURRENT_SCHEMA"
 
@@ -1363,7 +1363,7 @@ DROP SCHEMA pub_test3;
                                      Publication testpub2_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1374,7 +1374,7 @@ ALTER SCHEMA pub_test1 RENAME to pub_test1_renamed;
                                      Publication testpub2_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1_renamed"
     "pub_test2"
@@ -1384,7 +1384,7 @@ ALTER SCHEMA pub_test1_renamed RENAME to pub_test1;
                                      Publication testpub2_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1395,7 +1395,7 @@ ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test2;
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1407,7 +1407,7 @@ ERROR:  schema "non_existent_schema" does not exist
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1419,7 +1419,7 @@ ERROR:  schema "pub_test1" is already member of publication "testpub1_forschema"
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1430,7 +1430,7 @@ ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2;
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
 
@@ -1441,7 +1441,7 @@ ERROR:  tables from schema "pub_test2" are not part of the publication
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
 
@@ -1452,7 +1452,7 @@ ERROR:  schema "non_existent_schema" does not exist
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
 
@@ -1462,7 +1462,7 @@ ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test1;
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 (1 row)
 
 -- alter publication set multiple schema
@@ -1471,7 +1471,7 @@ ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test2;
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1483,7 +1483,7 @@ ERROR:  schema "non_existent_schema" does not exist
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1495,7 +1495,7 @@ ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test1;
                                      Publication testpub1_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
 
@@ -1577,7 +1577,7 @@ RESET client_min_messages;
                                      Publication testpub3_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 (1 row)
 
 ALTER PUBLICATION testpub3_forschema SET TABLES IN SCHEMA pub_test1;
@@ -1585,7 +1585,7 @@ ALTER PUBLICATION testpub3_forschema SET TABLES IN SCHEMA pub_test1;
                                      Publication testpub3_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables from schemas:
     "pub_test1"
 
@@ -1598,7 +1598,7 @@ RESET client_min_messages;
                                  Publication testpub_forschema_fortable
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "pub_test2.tbl1"
 Tables from schemas:
@@ -1608,7 +1608,7 @@ Tables from schemas:
                                  Publication testpub_fortable_forschema
           Owner           | All tables | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
 --------------------------+------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | f          | t       | t       | t       | t         | f
+ regress_publication_user | f          | f          | f       | t       | t       | t         | t
 Tables:
     "pub_test2.tbl1"
 Tables from schemas:
-- 
2.30.0.windows.2