v41-0005-Do-not-generate-WAL-log-for-non-top-level-DDL-co.patch

text/x-patch

Filename: v41-0005-Do-not-generate-WAL-log-for-non-top-level-DDL-co.patch
Type: text/x-patch
Part: 4
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 v41-0005
Subject: Do not generate WAL log for non-top-level DDL commands
File+
src/backend/catalog/aclchk.c 7 7
src/backend/catalog/pg_shdepend.c 3 2
src/backend/commands/ddl_deparse.c 2 3
src/backend/commands/event_trigger.c 24 5
src/backend/commands/extension.c 1 1
src/backend/commands/opclasscmds.c 20 15
src/backend/commands/publicationcmds.c 3 3
src/backend/commands/schemacmds.c 2 2
src/backend/commands/tablecmds.c 2 2
src/backend/commands/user.c 2 2
src/backend/tcop/utility.c 21 18
src/include/catalog/dependency.h 1 1
src/include/commands/defrem.h 3 3
src/include/commands/event_trigger.h 6 5
src/include/commands/schemacmds.h 2 1
src/include/commands/tablecmds.h 1 1
src/include/commands/user.h 1 1
src/include/tcop/deparse_utility.h 1 0
src/include/utils/acl.h 2 2
From a1cd491a8afa7d03f0a01ac41ac53aed974740cb Mon Sep 17 00:00:00 2001
From: "Zheng (Zane) Li" <zhelli@amazon.com>
Date: Sun, 27 Nov 2022 22:24:12 +0000
Subject: [PATCH v41 5/5] Do not generate WAL log for non-top-level DDL
 commands

---
 src/backend/catalog/aclchk.c           | 14 ++++-----
 src/backend/catalog/pg_shdepend.c      |  5 ++--
 src/backend/commands/ddl_deparse.c     |  5 ++--
 src/backend/commands/event_trigger.c   | 29 +++++++++++++++----
 src/backend/commands/extension.c       |  2 +-
 src/backend/commands/opclasscmds.c     | 35 +++++++++++++----------
 src/backend/commands/publicationcmds.c |  6 ++--
 src/backend/commands/schemacmds.c      |  4 +--
 src/backend/commands/tablecmds.c       |  4 +--
 src/backend/commands/user.c            |  4 +--
 src/backend/tcop/utility.c             | 39 ++++++++++++++------------
 src/include/catalog/dependency.h       |  2 +-
 src/include/commands/defrem.h          |  6 ++--
 src/include/commands/event_trigger.h   | 11 ++++----
 src/include/commands/schemacmds.h      |  3 +-
 src/include/commands/tablecmds.h       |  2 +-
 src/include/commands/user.h            |  2 +-
 src/include/tcop/deparse_utility.h     |  1 +
 src/include/utils/acl.h                |  4 +--
 19 files changed, 104 insertions(+), 74 deletions(-)

diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index db727c84c1..74a821959b 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -104,7 +104,7 @@ typedef struct
  */
 bool		binary_upgrade_record_init_privs = false;
 
-static void ExecGrantStmt_oids(InternalGrant *istmt);
+static void ExecGrantStmt_oids(InternalGrant *istmt, bool isTopLevelCommand);
 static void ExecGrant_Relation(InternalGrant *istmt);
 static void ExecGrant_Database(InternalGrant *istmt);
 static void ExecGrant_Fdw(InternalGrant *istmt);
@@ -383,7 +383,7 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
  * Called to execute the utility commands GRANT and REVOKE
  */
 void
-ExecuteGrantStmt(GrantStmt *stmt)
+ExecuteGrantStmt(GrantStmt *stmt, bool isTopLevelCommand)
 {
 	InternalGrant istmt;
 	ListCell   *cell;
@@ -584,7 +584,7 @@ ExecuteGrantStmt(GrantStmt *stmt)
 		}
 	}
 
-	ExecGrantStmt_oids(&istmt);
+	ExecGrantStmt_oids(&istmt, isTopLevelCommand);
 }
 
 /*
@@ -593,7 +593,7 @@ ExecuteGrantStmt(GrantStmt *stmt)
  * Internal entry point for granting and revoking privileges.
  */
 static void
-ExecGrantStmt_oids(InternalGrant *istmt)
+ExecGrantStmt_oids(InternalGrant *istmt, bool isTopLevelCommand)
 {
 	switch (istmt->objtype)
 	{
@@ -646,7 +646,7 @@ ExecGrantStmt_oids(InternalGrant *istmt)
 	 * granted.
 	 */
 	if (EventTriggerSupportsObjectType(istmt->objtype))
-		EventTriggerCollectGrant(istmt);
+		EventTriggerCollectGrant(istmt, isTopLevelCommand);
 }
 
 /*
@@ -1445,7 +1445,7 @@ SetDefaultACL(InternalDefaultACL *iacls)
  * Used by shdepDropOwned to remove mentions of a role in ACLs
  */
 void
-RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
+RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid, bool isTopLevelCommand)
 {
 	if (classid == DefaultAclRelationId)
 	{
@@ -1567,7 +1567,7 @@ RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
 		istmt.grant_option = false;
 		istmt.behavior = DROP_CASCADE;
 
-		ExecGrantStmt_oids(&istmt);
+		ExecGrantStmt_oids(&istmt, isTopLevelCommand);
 	}
 }
 
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index bc26bf1ef5..1c433af929 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -1292,7 +1292,7 @@ storeObjectDescription(StringInfo descs,
  * interdependent objects in the wrong order.
  */
 void
-shdepDropOwned(List *roleids, DropBehavior behavior)
+shdepDropOwned(List *roleids, DropBehavior behavior, bool isTopLevelCommand)
 {
 	Relation	sdepRel;
 	ListCell   *cell;
@@ -1408,7 +1408,8 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
 					{
 						RemoveRoleFromObjectACL(roleid,
 												sdepForm->classid,
-												sdepForm->objid);
+												sdepForm->objid,
+												isTopLevelCommand);
 						break;
 					}
 					/* FALLTHROUGH */
diff --git a/src/backend/commands/ddl_deparse.c b/src/backend/commands/ddl_deparse.c
index d69d5566c0..3bd39cda11 100755
--- a/src/backend/commands/ddl_deparse.c
+++ b/src/backend/commands/ddl_deparse.c
@@ -1087,8 +1087,6 @@ objtree_to_jsonb_rec(ObjTree *tree, JsonbParseState *state)
  * the given elements list.  The updated list is returned.
  *
  * This works for typed tables, regular tables, and domains.
- *
- * Note that CONSTRAINT_FOREIGN constraints are always ignored.
  */
 static List *
 obtainConstraints(List *elements, Oid relationId, Oid domainId)
@@ -1146,7 +1144,8 @@ obtainConstraints(List *elements, Oid relationId, Oid domainId)
 				contype = "check";
 				break;
 			case CONSTRAINT_FOREIGN:
-				continue;		/* not here */
+				contype = "foreign key";
+				break;
 			case CONSTRAINT_PRIMARY:
 				contype = "primary key";
 				break;
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index d242bdc909..d1be3331ec 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -878,7 +878,7 @@ EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason)
  *     to be executed.
  */
 void
-EventTriggerTableInitWriteStart(Node *parsetree)
+EventTriggerTableInitWriteStart(Node *parsetree, bool isTopLevelCommand)
 {
 	MemoryContext oldcxt;
 	CollectedCommand *command;
@@ -894,6 +894,7 @@ EventTriggerTableInitWriteStart(Node *parsetree)
 
 	command->type = SCT_CreateTableAs;
 	command->in_extension = creating_extension;
+	command->isTopLevelCommand = isTopLevelCommand;
 	command->d.ctas.address = InvalidObjectAddress;
 	command->d.ctas.real_create = NULL;
 	command->parsetree = copyObject(parsetree);
@@ -947,6 +948,10 @@ publication_deparse_table_init_write(PG_FUNCTION_ARGS)
 	cmd = currentEventTriggerState->currentCommand;
 	Assert(cmd);
 
+	/* Do not generate wal log for non-top level commands */
+	if (!cmd->isTopLevelCommand)
+		return PointerGetDatum(NULL);
+
 	relpersist = get_rel_persistence(cmd->d.simple.address.objectId);
 
 	/*
@@ -1646,7 +1651,8 @@ EventTriggerUndoInhibitCommandCollection(void)
 void
 EventTriggerCollectSimpleCommand(ObjectAddress address,
 								 ObjectAddress secondaryObject,
-								 Node *parsetree)
+								 Node *parsetree,
+								 bool isTopLevelCommand)
 {
 	MemoryContext oldcxt;
 	CollectedCommand *command;
@@ -1662,6 +1668,7 @@ EventTriggerCollectSimpleCommand(ObjectAddress address,
 
 	command->type = SCT_Simple;
 	command->in_extension = creating_extension;
+	command->isTopLevelCommand = isTopLevelCommand;
 
 	command->d.simple.address = address;
 	command->d.simple.secondaryObject = secondaryObject;
@@ -1682,7 +1689,7 @@ EventTriggerCollectSimpleCommand(ObjectAddress address,
  * add it to the command list.
  */
 void
-EventTriggerAlterTableStart(Node *parsetree)
+EventTriggerAlterTableStart(Node *parsetree, bool isTopLevelCommand)
 {
 	MemoryContext oldcxt;
 	CollectedCommand *command;
@@ -1698,6 +1705,7 @@ EventTriggerAlterTableStart(Node *parsetree)
 
 	command->type = SCT_AlterTable;
 	command->in_extension = creating_extension;
+	command->isTopLevelCommand = isTopLevelCommand;
 
 	command->d.alterTable.classId = RelationRelationId;
 	command->d.alterTable.objectId = InvalidOid;
@@ -1809,7 +1817,7 @@ EventTriggerAlterTableEnd(void)
  * not have the right lifetime.
  */
 void
-EventTriggerCollectGrant(InternalGrant *istmt)
+EventTriggerCollectGrant(InternalGrant *istmt, bool isTopLevelCommand)
 {
 	MemoryContext oldcxt;
 	CollectedCommand *command;
@@ -1838,6 +1846,7 @@ EventTriggerCollectGrant(InternalGrant *istmt)
 	command = palloc(sizeof(CollectedCommand));
 	command->type = SCT_Grant;
 	command->in_extension = creating_extension;
+	command->isTopLevelCommand = isTopLevelCommand;
 	command->d.grant.istmt = icopy;
 	command->parsetree = NULL;
 
@@ -1854,7 +1863,8 @@ EventTriggerCollectGrant(InternalGrant *istmt)
  */
 void
 EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
-							  List *operators, List *procedures)
+							  List *operators, List *procedures,
+							  bool isTopLevelCommand)
 {
 	MemoryContext oldcxt;
 	CollectedCommand *command;
@@ -1869,6 +1879,7 @@ EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
 	command = palloc(sizeof(CollectedCommand));
 	command->type = SCT_AlterOpFamily;
 	command->in_extension = creating_extension;
+	command->isTopLevelCommand = isTopLevelCommand;
 	ObjectAddressSet(command->d.opfam.address,
 					 OperatorFamilyRelationId, opfamoid);
 	command->d.opfam.operators = operators;
@@ -2427,6 +2438,10 @@ publication_deparse_table_rewrite(PG_FUNCTION_ARGS)
 
 	Assert(cmd && cmd->d.alterTable.rewrite);
 
+	/* Do not generate wal log for non-top level commands */
+	if (!cmd->isTopLevelCommand)
+		return PointerGetDatum(NULL);
+
 	relpersist = get_rel_persistence(cmd->d.alterTable.objectId);
 
 	/*
@@ -2473,6 +2488,10 @@ publication_deparse_ddl_command_end(PG_FUNCTION_ARGS)
 		CollectedCommand *cmd = lfirst(lc);
 		char	   *json_string;
 
+		/* Do not generate wal log for non-top level commands */
+		if (!cmd->isTopLevelCommand)
+			continue;
+
 		/* Rewrite DDL has been handled in table_rewrite trigger */
 		if (cmd->d.alterTable.rewrite)
 		{
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index cf1b1ca571..0e0ccec5a8 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1519,7 +1519,7 @@ CreateExtensionInternal(char *extensionName,
 			csstmt->schemaElts = NIL;
 			csstmt->if_not_exists = false;
 			CreateSchemaCommand(csstmt, "(generated CREATE SCHEMA command)",
-								-1, -1);
+								-1, -1, false);
 
 			/*
 			 * CreateSchemaCommand includes CommandCounterIncrement, so new
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 0bc6deda00..b3a69ea68b 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -52,11 +52,12 @@
 static void AlterOpFamilyAdd(AlterOpFamilyStmt *stmt,
 							 Oid amoid, Oid opfamilyoid,
 							 int maxOpNumber, int maxProcNumber,
-							 int optsProcNumber, List *items);
+							 int optsProcNumber, List *items,
+							 bool isTopLevelCommand);
 static void AlterOpFamilyDrop(AlterOpFamilyStmt *stmt,
 							  Oid amoid, Oid opfamilyoid,
 							  int maxOpNumber, int maxProcNumber,
-							  List *items);
+							  List *items, bool isTopLevelCommand);
 static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype);
 static void assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid);
 static void assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid,
@@ -241,7 +242,7 @@ get_opclass_oid(Oid amID, List *opclassname, bool missing_ok)
  */
 static ObjectAddress
 CreateOpFamily(CreateOpFamilyStmt *stmt, const char *opfname,
-			   Oid namespaceoid, Oid amoid)
+			   Oid namespaceoid, Oid amoid, bool isTopLevelCommand)
 {
 	Oid			opfamilyoid;
 	Relation	rel;
@@ -315,7 +316,7 @@ CreateOpFamily(CreateOpFamilyStmt *stmt, const char *opfname,
 
 	/* Report the new operator family to possibly interested event triggers */
 	EventTriggerCollectSimpleCommand(myself, InvalidObjectAddress,
-									 (Node *) stmt);
+									 (Node *) stmt, isTopLevelCommand);
 
 	/* Post creation hook for new operator family */
 	InvokeObjectPostCreateHook(OperatorFamilyRelationId, opfamilyoid, 0);
@@ -330,7 +331,7 @@ CreateOpFamily(CreateOpFamilyStmt *stmt, const char *opfname,
  *		Define a new index operator class.
  */
 ObjectAddress
-DefineOpClass(CreateOpClassStmt *stmt)
+DefineOpClass(CreateOpClassStmt *stmt, bool isTopLevelCommand)
 {
 	char	   *opcname;		/* name of opclass we're creating */
 	Oid			amoid,			/* our AM's oid */
@@ -462,7 +463,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 			/*
 			 * Create it ... again no need for more permissions ...
 			 */
-			tmpAddr = CreateOpFamily(opfstmt, opcname, namespaceoid, amoid);
+			tmpAddr = CreateOpFamily(opfstmt, opcname, namespaceoid, amoid, isTopLevelCommand);
 			opfamilyoid = tmpAddr.objectId;
 		}
 	}
@@ -769,7 +770,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
  *		Define a new index operator family.
  */
 ObjectAddress
-DefineOpFamily(CreateOpFamilyStmt *stmt)
+DefineOpFamily(CreateOpFamilyStmt *stmt, bool isTopLevelCommand)
 {
 	char	   *opfname;		/* name of opfamily we're creating */
 	Oid			amoid,			/* our AM's oid */
@@ -801,7 +802,7 @@ DefineOpFamily(CreateOpFamilyStmt *stmt)
 				 errmsg("must be superuser to create an operator family")));
 
 	/* Insert pg_opfamily catalog entry */
-	return CreateOpFamily(stmt, opfname, namespaceoid, amoid);
+	return CreateOpFamily(stmt, opfname, namespaceoid, amoid, isTopLevelCommand);
 }
 
 
@@ -814,7 +815,7 @@ DefineOpFamily(CreateOpFamilyStmt *stmt)
  * different code paths.
  */
 Oid
-AlterOpFamily(AlterOpFamilyStmt *stmt)
+(AlterOpFamily)(AlterOpFamilyStmt *stmt, bool isTopLevelCommand)
 {
 	Oid			amoid,			/* our AM's oid */
 				opfamilyoid;	/* oid of opfamily */
@@ -865,11 +866,12 @@ AlterOpFamily(AlterOpFamilyStmt *stmt)
 	 */
 	if (stmt->isDrop)
 		AlterOpFamilyDrop(stmt, amoid, opfamilyoid,
-						  maxOpNumber, maxProcNumber, stmt->items);
+						  maxOpNumber, maxProcNumber,
+						  stmt->items, isTopLevelCommand);
 	else
 		AlterOpFamilyAdd(stmt, amoid, opfamilyoid,
 						 maxOpNumber, maxProcNumber, optsProcNumber,
-						 stmt->items);
+						 stmt->items, isTopLevelCommand);
 
 	return opfamilyoid;
 }
@@ -880,7 +882,7 @@ AlterOpFamily(AlterOpFamilyStmt *stmt)
 static void
 AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 				 int maxOpNumber, int maxProcNumber, int optsProcNumber,
-				 List *items)
+				 List *items, bool isTopLevelCommand)
 {
 	IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false);
 	List	   *operators;		/* OpFamilyMember list for operators */
@@ -1020,7 +1022,8 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 
 	/* make information available to event triggers */
 	EventTriggerCollectAlterOpFam(stmt, opfamilyoid,
-								  operators, procedures);
+								  operators, procedures,
+								  isTopLevelCommand);
 }
 
 /*
@@ -1028,7 +1031,8 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
  */
 static void
 AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
-				  int maxOpNumber, int maxProcNumber, List *items)
+				  int maxOpNumber, int maxProcNumber, List *items,
+				  bool isTopLevelCommand)
 {
 	List	   *operators;		/* OpFamilyMember list for operators */
 	List	   *procedures;		/* OpFamilyMember list for support procs */
@@ -1097,7 +1101,8 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 
 	/* make information available to event triggers */
 	EventTriggerCollectAlterOpFam(stmt, opfamilyoid,
-								  operators, procedures);
+								  operators, procedures,
+								  isTopLevelCommand);
 }
 
 
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index e923cc6973..0ba90ba755 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -1245,7 +1245,7 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
 
 	ObjectAddressSet(obj, PublicationRelationId, pubform->oid);
 	EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
-									 (Node *) stmt);
+									 (Node *) stmt, true);
 
 	InvokeObjectPostAlterHook(PublicationRelationId, pubform->oid, 0);
 }
@@ -1965,7 +1965,7 @@ PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
 		if (stmt)
 		{
 			EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
-											 (Node *) stmt);
+											 (Node *) stmt, true);
 
 			InvokeObjectPostCreateHook(PublicationRelRelationId,
 									   obj.objectId, 0);
@@ -2038,7 +2038,7 @@ PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists,
 		if (stmt)
 		{
 			EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
-											 (Node *) stmt);
+											 (Node *) stmt, true);
 
 			InvokeObjectPostCreateHook(PublicationNamespaceRelationId,
 									   obj.objectId, 0);
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 12cbfba7d0..ca9ce399ac 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -49,7 +49,7 @@ static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerI
  */
 Oid
 CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
-					int stmt_location, int stmt_len)
+					int stmt_location, int stmt_len, bool isTopLevelCommand)
 {
 	const char *schemaName = stmt->schemaname;
 	Oid			namespaceId;
@@ -170,7 +170,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
 	 */
 	ObjectAddressSet(address, NamespaceRelationId, namespaceId);
 	EventTriggerCollectSimpleCommand(address, InvalidObjectAddress,
-									 (Node *) stmt);
+									 (Node *) stmt, isTopLevelCommand);
 
 	/*
 	 * Examine the list of commands embedded in the CREATE SCHEMA command, and
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 634d5e858b..1603e96b95 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -14505,7 +14505,7 @@ ATExecSetTableSpaceNoStorage(Relation rel, Oid newTableSpace)
  * lock can't be acquired then we ereport(ERROR).
  */
 Oid
-AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
+AlterTableMoveAll(AlterTableMoveAllStmt *stmt, bool isTopLevelCommand)
 {
 	List	   *relations = NIL;
 	ListCell   *l;
@@ -14657,7 +14657,7 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
 
 		cmds = lappend(cmds, cmd);
 
-		EventTriggerAlterTableStart((Node *) stmt);
+		EventTriggerAlterTableStart((Node *) stmt, isTopLevelCommand);
 		/* OID is set by AlterTableInternal */
 		AlterTableInternal(lfirst_oid(l), cmds, false);
 		EventTriggerAlterTableEnd();
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 8b6543edee..5cbed9af88 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1464,7 +1464,7 @@ GrantRole(ParseState *pstate, GrantRoleStmt *stmt)
  * Drop the objects owned by a given list of roles.
  */
 void
-DropOwnedObjects(DropOwnedStmt *stmt)
+DropOwnedObjects(DropOwnedStmt *stmt, bool isTopLevelCommand)
 {
 	List	   *role_ids = roleSpecsToIds(stmt->roles);
 	ListCell   *cell;
@@ -1481,7 +1481,7 @@ DropOwnedObjects(DropOwnedStmt *stmt)
 	}
 
 	/* Ok, do it */
-	shdepDropOwned(role_ids, stmt->behavior);
+	shdepDropOwned(role_ids, stmt->behavior, isTopLevelCommand);
 }
 
 /*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 50839c0d96..06b60b25bc 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -974,7 +974,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
 									   context, params, queryEnv,
 									   dest, qc);
 				else
-					ExecuteGrantStmt(stmt);
+					ExecuteGrantStmt(stmt, context == PROCESS_UTILITY_TOPLEVEL);
 			}
 			break;
 
@@ -1128,7 +1128,8 @@ ProcessUtilitySlow(ParseState *pstate,
 				CreateSchemaCommand((CreateSchemaStmt *) parsetree,
 									queryString,
 									pstmt->stmt_location,
-									pstmt->stmt_len);
+									pstmt->stmt_len,
+									isTopLevel);
 
 				/*
 				 * EventTriggerCollectSimpleCommand called by
@@ -1174,7 +1175,8 @@ ProcessUtilitySlow(ParseState *pstate,
 													 queryString);
 							EventTriggerCollectSimpleCommand(address,
 															 secondaryObject,
-															 stmt);
+															 stmt,
+															 isTopLevel);
 
 							/*
 							 * Let NewRelationCreateToastTable decide if this
@@ -1215,7 +1217,8 @@ ProcessUtilitySlow(ParseState *pstate,
 											   address.objectId);
 							EventTriggerCollectSimpleCommand(address,
 															 secondaryObject,
-															 stmt);
+															 stmt,
+															 isTopLevel);
 						}
 						else if (IsA(stmt, TableLikeClause))
 						{
@@ -1318,7 +1321,7 @@ ProcessUtilitySlow(ParseState *pstate,
 						atcontext.queryEnv = queryEnv;
 
 						/* ... ensure we have an event trigger context ... */
-						EventTriggerAlterTableStart(parsetree);
+						EventTriggerAlterTableStart(parsetree, isTopLevel);
 						EventTriggerAlterTableRelid(relid);
 
 						/* ... and do it */
@@ -1539,7 +1542,7 @@ ProcessUtilitySlow(ParseState *pstate,
 					stmt = transformIndexStmt(relid, stmt, queryString);
 
 					/* ... and do it */
-					EventTriggerAlterTableStart(parsetree);
+					EventTriggerAlterTableStart(parsetree, isTopLevel);
 					address =
 						DefineIndex(relid,	/* OID of heap relation */
 									stmt,
@@ -1558,7 +1561,7 @@ ProcessUtilitySlow(ParseState *pstate,
 					 * code, we need them to appear after this one.
 					 */
 					EventTriggerCollectSimpleCommand(address, secondaryObject,
-													 parsetree);
+													 parsetree, isTopLevel);
 					commandCollected = true;
 					EventTriggerAlterTableEnd();
 				}
@@ -1635,11 +1638,11 @@ ProcessUtilitySlow(ParseState *pstate,
 				break;
 
 			case T_ViewStmt:	/* CREATE VIEW */
-				EventTriggerAlterTableStart(parsetree);
+				EventTriggerAlterTableStart(parsetree, isTopLevel);
 				address = DefineView((ViewStmt *) parsetree, queryString,
 									 pstmt->stmt_location, pstmt->stmt_len);
 				EventTriggerCollectSimpleCommand(address, secondaryObject,
-												 parsetree);
+												 parsetree, isTopLevel);
 				/* stashed internally */
 				commandCollected = true;
 				EventTriggerAlterTableEnd();
@@ -1666,7 +1669,7 @@ ProcessUtilitySlow(ParseState *pstate,
 				break;
 
 			case T_CreateTableAsStmt:
-				EventTriggerTableInitWriteStart(parsetree);
+				EventTriggerTableInitWriteStart(parsetree, isTopLevel);
 				address = ExecCreateTableAs(pstate, (CreateTableAsStmt *) parsetree,
 											params, queryEnv, qc);
 				EventTriggerTableInitWriteEnd();
@@ -1717,13 +1720,13 @@ ProcessUtilitySlow(ParseState *pstate,
 				break;
 
 			case T_CreateOpClassStmt:
-				DefineOpClass((CreateOpClassStmt *) parsetree);
+				DefineOpClass((CreateOpClassStmt *) parsetree, isTopLevel);
 				/* command is stashed in DefineOpClass */
 				commandCollected = true;
 				break;
 
 			case T_CreateOpFamilyStmt:
-				address = DefineOpFamily((CreateOpFamilyStmt *) parsetree);
+				address = DefineOpFamily((CreateOpFamilyStmt *) parsetree, isTopLevel);
 
 				/*
 				 * DefineOpFamily calls EventTriggerCollectSimpleCommand
@@ -1737,7 +1740,7 @@ ProcessUtilitySlow(ParseState *pstate,
 				break;
 
 			case T_AlterOpFamilyStmt:
-				AlterOpFamily((AlterOpFamilyStmt *) parsetree);
+				AlterOpFamily((AlterOpFamilyStmt *) parsetree, isTopLevel);
 				/* commands are stashed in AlterOpFamily */
 				commandCollected = true;
 				break;
@@ -1758,7 +1761,7 @@ ProcessUtilitySlow(ParseState *pstate,
 				break;
 
 			case T_AlterTableMoveAllStmt:
-				AlterTableMoveAll((AlterTableMoveAllStmt *) parsetree);
+				AlterTableMoveAll((AlterTableMoveAllStmt *) parsetree, isTopLevel);
 				/* commands are stashed in AlterTableMoveAll */
 				commandCollected = true;
 				break;
@@ -1802,13 +1805,13 @@ ProcessUtilitySlow(ParseState *pstate,
 				break;
 
 			case T_GrantStmt:
-				ExecuteGrantStmt((GrantStmt *) parsetree);
+				ExecuteGrantStmt((GrantStmt *) parsetree, isTopLevel);
 				/* commands are stashed in ExecGrantStmt_oids */
 				commandCollected = true;
 				break;
 
 			case T_DropOwnedStmt:
-				DropOwnedObjects((DropOwnedStmt *) parsetree);
+				DropOwnedObjects((DropOwnedStmt *) parsetree, isTopLevel);
 				/* no commands stashed for DROP */
 				commandCollected = true;
 				break;
@@ -1918,7 +1921,7 @@ ProcessUtilitySlow(ParseState *pstate,
 		 */
 		if (!commandCollected)
 			EventTriggerCollectSimpleCommand(address, secondaryObject,
-											 parsetree);
+											 parsetree, isTopLevel);
 
 		if (isCompleteQuery)
 		{
@@ -1977,7 +1980,7 @@ ProcessUtilityForAlterTable(Node *stmt, AlterTableUtilityContext *context)
 				   None_Receiver,
 				   NULL);
 
-	EventTriggerAlterTableStart(context->pstmt->utilityStmt);
+	EventTriggerAlterTableStart(context->pstmt->utilityStmt, false);
 	EventTriggerAlterTableRelid(context->relid);
 }
 
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 98a1a84289..74a64e8796 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -263,7 +263,7 @@ extern void copyTemplateDependencies(Oid templateDbId, Oid newDbId);
 
 extern void dropDatabaseDependencies(Oid databaseId);
 
-extern void shdepDropOwned(List *roleids, DropBehavior behavior);
+extern void shdepDropOwned(List *roleids, DropBehavior behavior, bool isTopLevelCommand);
 
 extern void shdepReassignOwned(List *roleids, Oid newrole);
 
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 1d3ce246c9..f23315ef4b 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -91,9 +91,9 @@ extern ObjectAddress DefineAggregate(ParseState *pstate, List *name, List *args,
 									 List *parameters, bool replace);
 
 /* commands/opclasscmds.c */
-extern ObjectAddress DefineOpClass(CreateOpClassStmt *stmt);
-extern ObjectAddress DefineOpFamily(CreateOpFamilyStmt *stmt);
-extern Oid	AlterOpFamily(AlterOpFamilyStmt *stmt);
+extern ObjectAddress DefineOpClass(CreateOpClassStmt *stmt, bool isTopLevelCommand);
+extern ObjectAddress DefineOpFamily(CreateOpFamilyStmt *stmt, bool isTopLevelCommand);
+extern Oid	AlterOpFamily(AlterOpFamilyStmt *stmt, bool isTopLevelCommand);
 extern void IsThereOpClassInNamespace(const char *opcname, Oid opcmethod,
 									  Oid opcnamespace);
 extern void IsThereOpFamilyInNamespace(const char *opfname, Oid opfmethod,
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index a9e0f71f6a..b9a1850754 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -55,7 +55,7 @@ extern void EventTriggerDDLCommandEnd(Node *parsetree);
 extern void EventTriggerSQLDrop(Node *parsetree);
 extern void EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason);
 
-extern void EventTriggerTableInitWriteStart(Node *parsetree);
+extern void EventTriggerTableInitWriteStart(Node *parsetree, bool isTopLevelCommand);
 extern void EventTriggerTableInitWrite(Node *parsetree, ObjectAddress address);
 extern void EventTriggerTableInitWriteEnd(void);
 
@@ -70,19 +70,20 @@ extern void EventTriggerUndoInhibitCommandCollection(void);
 
 extern void EventTriggerCollectSimpleCommand(ObjectAddress address,
 											 ObjectAddress secondaryObject,
-											 Node *parsetree);
+											 Node *parsetree,
+											 bool isTopLevelCommand);
 
-extern void EventTriggerAlterTableStart(Node *parsetree);
+extern void EventTriggerAlterTableStart(Node *parsetree, bool isTopLevelCommand);
 extern void EventTriggerAlterTableRelid(Oid objectId);
 extern void EventTriggerCollectAlterTableSubcmd(Node *subcmd,
 												ObjectAddress address,
 												bool rewrite);
 extern void EventTriggerAlterTableEnd(void);
 
-extern void EventTriggerCollectGrant(InternalGrant *istmt);
+extern void EventTriggerCollectGrant(InternalGrant *istmt, bool isTopLevelCommand);
 extern void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt,
 										  Oid opfamoid, List *operators,
-										  List *procedures);
+										  List *procedures, bool isTopLevelCommand);
 extern void EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt,
 											 Oid opcoid, List *operators,
 											 List *procedures);
diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h
index e6eb2aaa60..3740064718 100644
--- a/src/include/commands/schemacmds.h
+++ b/src/include/commands/schemacmds.h
@@ -20,7 +20,8 @@
 
 extern Oid	CreateSchemaCommand(CreateSchemaStmt *stmt,
 								const char *queryString,
-								int stmt_location, int stmt_len);
+								int stmt_location, int stmt_len,
+								bool isTopLevelCommand);
 
 extern ObjectAddress RenameSchema(const char *oldname, const char *newname);
 extern ObjectAddress AlterSchemaOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 03f14d6be1..6eae4a5b09 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -40,7 +40,7 @@ extern void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, L
 
 extern void AlterTableInternal(Oid relid, List *cmds, bool recurse);
 
-extern Oid	AlterTableMoveAll(AlterTableMoveAllStmt *stmt);
+extern Oid	AlterTableMoveAll(AlterTableMoveAllStmt *stmt, bool isTopLevelCommand);
 
 extern ObjectAddress AlterTableNamespace(AlterObjectSchemaStmt *stmt,
 										 Oid *oldschema);
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 54c720d880..adf5354f8e 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -30,7 +30,7 @@ extern Oid	AlterRoleSet(AlterRoleSetStmt *stmt);
 extern void DropRole(DropRoleStmt *stmt);
 extern void GrantRole(ParseState *pstate, GrantRoleStmt *stmt);
 extern ObjectAddress RenameRole(const char *oldname, const char *newname);
-extern void DropOwnedObjects(DropOwnedStmt *stmt);
+extern void DropOwnedObjects(DropOwnedStmt *stmt, bool isTopLevelCommand);
 extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt);
 extern List *roleSpecsToIds(List *memberNames);
 
diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h
index 3d294a0371..c829d4ec82 100644
--- a/src/include/tcop/deparse_utility.h
+++ b/src/include/tcop/deparse_utility.h
@@ -47,6 +47,7 @@ typedef struct CollectedCommand
 	CollectedCommandType type;
 
 	bool		in_extension;
+	bool		isTopLevelCommand;
 	Node	   *parsetree;
 
 	union
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 406071037e..85727a33a8 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -231,10 +231,10 @@ extern void initialize_acl(void);
 /*
  * prototypes for functions in aclchk.c
  */
-extern void ExecuteGrantStmt(GrantStmt *stmt);
+extern void ExecuteGrantStmt(GrantStmt *stmt, bool isTopLevelCommand);
 extern void ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *stmt);
 
-extern void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid);
+extern void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid, bool isTopLevelCommand);
 
 extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
 								AclMode mask, AclMaskHow how);
-- 
2.34.1