Hi all,

This is a continuation of the work that has been previously discussed
here, resulting mainly in e3931d0 for pg_attribute and pg_shdepend:
https://www.postgresql.org/message-id/20190213182737.mxn6hkdxwrzgx...@alap3.anarazel.de

I have been looking at the amount of work that could be done
independently for pg_depend, and attached are two patches:
- 0001 switches recordMultipleDependencies() to use multi-inserts.
Contrary to pg_attribute and pg_shdepend, the number of items to
insert is known in advance, but some of them can be skipped if known
as a pinned dependency.  The data insertion is capped at 64kB, and the
number of slots is basically calculation from the maximum cap and the
number of items to insert.
- 0002 switches a bunch of code paths to make use of multi-inserts
instead of individual calls to recordDependencyOn(), grouping the
insertions of dependencies of the same time.  This relies on the
existing set of APIs to manipulate a set of object addresses, without
any new addition there (no reset-like routine either as I noticed that
it would have been useful in only one place).  The set of changes is
honestly a bit bulky here.

I am adding this thread to the next commit fest.  Thoughts are
welcome.

Thanks,
--
Michael
From cd117fa88938c89ac953a5e3c036828337150b07 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Fri, 7 Aug 2020 10:57:40 +0900
Subject: [PATCH 1/2] Use multi-inserts for pg_depend

This is a follow-up of the work done in e3931d01.  This case is a bit
different than pg_attribute and pg_shdepend: the maximum number of items
to insert is known in advance, but there is no need to handle pinned
dependencies.  Hence, the base allocation for slots is done based on the
number of items and the maximum allowed with a cap at 64kB, and items
are initialized once used to minimize the overhead of the operation.

Author: Daniel Gustafsson, Michael Paquier
Discussion: https://postgr.es/m/XXX
---
 src/backend/catalog/pg_depend.c | 95 ++++++++++++++++++++++++---------
 1 file changed, 69 insertions(+), 26 deletions(-)

diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 70baf03178..596f0c5e29 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -47,6 +47,12 @@ recordDependencyOn(const ObjectAddress *depender,
 	recordMultipleDependencies(depender, referenced, 1, behavior);
 }
 
+/*
+ * Cap the maximum amount of bytes allocated for recordMultipleDependencies()
+ * slots.
+ */
+#define MAX_PGDEPEND_INSERT_BYTES	65535
+
 /*
  * Record multiple dependencies (of the same kind) for a single dependent
  * object.  This has a little less overhead than recording each separately.
@@ -59,10 +65,10 @@ recordMultipleDependencies(const ObjectAddress *depender,
 {
 	Relation	dependDesc;
 	CatalogIndexState indstate;
-	HeapTuple	tup;
-	int			i;
-	bool		nulls[Natts_pg_depend];
-	Datum		values[Natts_pg_depend];
+	int			slotCount, i;
+	TupleTableSlot **slot;
+	int			nslots, max_slots;
+	bool		slot_init = true;
 
 	if (nreferenced <= 0)
 		return;					/* nothing to do */
@@ -76,11 +82,18 @@ recordMultipleDependencies(const ObjectAddress *depender,
 
 	dependDesc = table_open(DependRelationId, RowExclusiveLock);
 
+	/*
+	 * Allocate the slots to use, but delay initialization until we know that
+	 * they will be used.
+	 */
+	max_slots = Min(nreferenced,
+					MAX_PGDEPEND_INSERT_BYTES / sizeof(FormData_pg_depend));
+	slot = palloc(sizeof(TupleTableSlot *) * max_slots);
+
 	/* Don't open indexes unless we need to make an update */
 	indstate = NULL;
 
-	memset(nulls, false, sizeof(nulls));
-
+	slotCount = 0;
 	for (i = 0; i < nreferenced; i++, referenced++)
 	{
 		/*
@@ -88,38 +101,68 @@ recordMultipleDependencies(const ObjectAddress *depender,
 		 * need to record dependencies on it.  This saves lots of space in
 		 * pg_depend, so it's worth the time taken to check.
 		 */
-		if (!isObjectPinned(referenced, dependDesc))
+		if (isObjectPinned(referenced, dependDesc))
+			continue;
+
+		if (slot_init)
+			slot[slotCount] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc),
+													   &TTSOpsHeapTuple);
+
+		ExecClearTuple(slot[slotCount]);
+
+		/*
+		 * Record the Dependency.  Note we don't bother to check for duplicate
+		 * dependencies; there's no harm in them.
+		 */
+		slot[slotCount]->tts_values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
+		slot[slotCount]->tts_values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
+		slot[slotCount]->tts_values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
+		slot[slotCount]->tts_values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
+		slot[slotCount]->tts_values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
+		slot[slotCount]->tts_values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
+		slot[slotCount]->tts_values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
+
+		memset(slot[slotCount]->tts_isnull, false,
+			   slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool));
+
+		ExecStoreVirtualTuple(slot[slotCount]);
+		slotCount++;
+
+		/* If slots are full, insert a batch of tuples */
+		if (slotCount == max_slots)
 		{
-			/*
-			 * Record the Dependency.  Note we don't bother to check for
-			 * duplicate dependencies; there's no harm in them.
-			 */
-			values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
-			values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
-			values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
-
-			values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
-			values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
-			values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
-
-			values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
-
-			tup = heap_form_tuple(dependDesc->rd_att, values, nulls);
-
 			/* fetch index info only when we know we need it */
 			if (indstate == NULL)
 				indstate = CatalogOpenIndexes(dependDesc);
 
-			CatalogTupleInsertWithInfo(dependDesc, tup, indstate);
-
-			heap_freetuple(tup);
+			CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slotCount,
+											 indstate);
+			slotCount = 0;
+			slot_init = false;
 		}
 	}
 
+	/* Insert any tuples left in the buffer */
+	if (slotCount > 0)
+	{
+		/* fetch index info only when we know we need it */
+		if (indstate == NULL)
+			indstate = CatalogOpenIndexes(dependDesc);
+
+		CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slotCount,
+										 indstate);
+	}
+
 	if (indstate != NULL)
 		CatalogCloseIndexes(indstate);
 
 	table_close(dependDesc, RowExclusiveLock);
+
+	/* Drop only the number of slots used */
+	nslots = slot_init ? slotCount : max_slots;
+	for (i = 0; i < nslots; i++)
+		ExecDropSingleTupleTableSlot(slot[i]);
+	pfree(slot);
 }
 
 /*
-- 
2.28.0

From fcc0a11e9fc94d2fedc71dd10ba2a23713225963 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Fri, 7 Aug 2020 15:14:51 +0900
Subject: [PATCH 2/2] Switch to multi-insert dependencies for many code paths

This makes use of the new APIs to insert dependencies in groups, instead
of doing the operation one-by-one.
---
 src/backend/catalog/heap.c                 | 59 +++++++-------
 src/backend/catalog/index.c                | 21 ++++-
 src/backend/catalog/pg_aggregate.c         | 23 +++---
 src/backend/catalog/pg_cast.c              | 28 ++++---
 src/backend/catalog/pg_constraint.c        | 34 +++++---
 src/backend/catalog/pg_operator.c          | 20 +++--
 src/backend/catalog/pg_proc.c              | 30 +++++---
 src/backend/catalog/pg_range.c             | 39 ++++------
 src/backend/catalog/pg_type.c              | 62 ++++++++-------
 src/backend/commands/functioncmds.c        | 34 ++++----
 src/backend/commands/proclang.c            | 24 +++---
 src/backend/commands/tsearchcmds.c         | 90 +++++++++++-----------
 src/test/regress/expected/create_index.out |  6 +-
 13 files changed, 250 insertions(+), 220 deletions(-)

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index f2ca686397..0683e3bdfa 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -1434,15 +1434,9 @@ heap_create_with_catalog(const char *relname,
 	{
 		ObjectAddress myself,
 					referenced;
+		ObjectAddresses *addrs;
 
-		myself.classId = RelationRelationId;
-		myself.objectId = relid;
-		myself.objectSubId = 0;
-
-		referenced.classId = NamespaceRelationId;
-		referenced.objectId = relnamespace;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(myself, RelationRelationId, relid);
 
 		recordDependencyOnOwner(RelationRelationId, relid, ownerid);
 
@@ -1450,12 +1444,15 @@ heap_create_with_catalog(const char *relname,
 
 		recordDependencyOnCurrentExtension(&myself, false);
 
+		addrs = new_object_addresses();
+
+		ObjectAddressSet(referenced, NamespaceRelationId, relnamespace);
+		add_exact_object_address(&referenced, addrs);
+
 		if (reloftypeid)
 		{
-			referenced.classId = TypeRelationId;
-			referenced.objectId = reloftypeid;
-			referenced.objectSubId = 0;
-			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+			ObjectAddressSet(referenced, TypeRelationId, reloftypeid);
+			add_exact_object_address(&referenced, addrs);
 		}
 
 		/*
@@ -1468,11 +1465,12 @@ heap_create_with_catalog(const char *relname,
 		if (relkind == RELKIND_RELATION ||
 			relkind == RELKIND_MATVIEW)
 		{
-			referenced.classId = AccessMethodRelationId;
-			referenced.objectId = accessmtd;
-			referenced.objectSubId = 0;
-			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+			ObjectAddressSet(referenced, AccessMethodRelationId, accessmtd);
+			add_exact_object_address(&referenced, addrs);
 		}
+
+		record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+		free_object_addresses(addrs);
 	}
 
 	/* Post creation hook for new relation */
@@ -3580,6 +3578,7 @@ StorePartitionKey(Relation rel,
 	bool		nulls[Natts_pg_partitioned_table];
 	ObjectAddress myself;
 	ObjectAddress referenced;
+	ObjectAddresses *addrs;
 
 	Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
 
@@ -3623,31 +3622,27 @@ StorePartitionKey(Relation rel,
 	table_close(pg_partitioned_table, RowExclusiveLock);
 
 	/* Mark this relation as dependent on a few things as follows */
-	myself.classId = RelationRelationId;
-	myself.objectId = RelationGetRelid(rel);
-	myself.objectSubId = 0;
+	addrs = new_object_addresses();
+	ObjectAddressSet(myself, RelationRelationId, RelationGetRelid(rel));
 
 	/* Operator class and collation per key column */
 	for (i = 0; i < partnatts; i++)
 	{
-		referenced.classId = OperatorClassRelationId;
-		referenced.objectId = partopclass[i];
-		referenced.objectSubId = 0;
-
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(referenced, OperatorClassRelationId, partopclass[i]);
+		add_exact_object_address(&referenced, addrs);
 
 		/* The default collation is pinned, so don't bother recording it */
 		if (OidIsValid(partcollation[i]) &&
 			partcollation[i] != DEFAULT_COLLATION_OID)
 		{
-			referenced.classId = CollationRelationId;
-			referenced.objectId = partcollation[i];
-			referenced.objectSubId = 0;
-
-			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+			ObjectAddressSet(referenced, CollationRelationId, partcollation[i]);
+			add_exact_object_address(&referenced, addrs);
 		}
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
+
 	/*
 	 * The partitioning columns are made internally dependent on the table,
 	 * because we cannot drop any of them without dropping the whole table.
@@ -3659,10 +3654,8 @@ StorePartitionKey(Relation rel,
 		if (partattrs[i] == 0)
 			continue;			/* ignore expressions here */
 
-		referenced.classId = RelationRelationId;
-		referenced.objectId = RelationGetRelid(rel);
-		referenced.objectSubId = partattrs[i];
-
+		ObjectAddressSubSet(referenced, RelationRelationId,
+							RelationGetRelid(rel), partattrs[i]);
 		recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
 	}
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1be27eec52..6cc9f1bfbe 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1018,6 +1018,7 @@ index_create(Relation heapRelation,
 	{
 		ObjectAddress myself,
 					referenced;
+		ObjectAddresses *addrs;
 
 		ObjectAddressSet(myself, RelationRelationId, indexRelationId);
 
@@ -1054,6 +1055,8 @@ index_create(Relation heapRelation,
 		{
 			bool		have_simple_col = false;
 
+			addrs = new_object_addresses();
+
 			/* Create auto dependencies on simply-referenced columns */
 			for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
 			{
@@ -1062,7 +1065,7 @@ index_create(Relation heapRelation,
 					ObjectAddressSubSet(referenced, RelationRelationId,
 										heapRelationId,
 										indexInfo->ii_IndexAttrNumbers[i]);
-					recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+					add_exact_object_address(&referenced, addrs);
 					have_simple_col = true;
 				}
 			}
@@ -1077,8 +1080,11 @@ index_create(Relation heapRelation,
 			{
 				ObjectAddressSet(referenced, RelationRelationId,
 								 heapRelationId);
-				recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+				add_exact_object_address(&referenced, addrs);
 			}
+
+			record_object_address_dependencies(&myself, addrs, DEPENDENCY_AUTO);
+			free_object_addresses(addrs);
 		}
 
 		/*
@@ -1096,7 +1102,11 @@ index_create(Relation heapRelation,
 			recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC);
 		}
 
+		/* placeholder for normal dependencies */
+		addrs = new_object_addresses();
+
 		/* Store dependency on collations */
+
 		/* The default collation is pinned, so don't bother recording it */
 		for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
 		{
@@ -1105,7 +1115,7 @@ index_create(Relation heapRelation,
 			{
 				ObjectAddressSet(referenced, CollationRelationId,
 								 collationObjectId[i]);
-				recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+				add_exact_object_address(&referenced, addrs);
 			}
 		}
 
@@ -1113,9 +1123,12 @@ index_create(Relation heapRelation,
 		for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
 		{
 			ObjectAddressSet(referenced, OperatorClassRelationId, classObjectId[i]);
-			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+			add_exact_object_address(&referenced, addrs);
 		}
 
+		record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+		free_object_addresses(addrs);
+
 		/* Store dependencies on anything mentioned in index expressions */
 		if (indexInfo->ii_Expressions)
 		{
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 89007ad1ed..a0554f0d79 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -105,6 +105,7 @@ AggregateCreate(const char *aggName,
 	int			i;
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs;
 	AclResult	aclresult;
 
 	/* sanity checks (caller should have caught these) */
@@ -741,66 +742,70 @@ AggregateCreate(const char *aggName,
 	 * way.
 	 */
 
+	addrs = new_object_addresses();
+
 	/* Depends on transition function */
 	ObjectAddressSet(referenced, ProcedureRelationId, transfn);
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	add_exact_object_address(&referenced, addrs);
 
 	/* Depends on final function, if any */
 	if (OidIsValid(finalfn))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, finalfn);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Depends on combine function, if any */
 	if (OidIsValid(combinefn))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, combinefn);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Depends on serialization function, if any */
 	if (OidIsValid(serialfn))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, serialfn);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Depends on deserialization function, if any */
 	if (OidIsValid(deserialfn))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, deserialfn);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Depends on forward transition function, if any */
 	if (OidIsValid(mtransfn))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, mtransfn);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Depends on inverse transition function, if any */
 	if (OidIsValid(minvtransfn))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, minvtransfn);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Depends on final function, if any */
 	if (OidIsValid(mfinalfn))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, mfinalfn);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Depends on sort operator, if any */
 	if (OidIsValid(sortop))
 	{
 		ObjectAddressSet(referenced, OperatorRelationId, sortop);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
 	return myself;
 }
 
diff --git a/src/backend/catalog/pg_cast.c b/src/backend/catalog/pg_cast.c
index 5ea2b82b08..c03e82d74f 100644
--- a/src/backend/catalog/pg_cast.c
+++ b/src/backend/catalog/pg_cast.c
@@ -50,6 +50,7 @@ CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, char castcontext,
 	bool		nulls[Natts_pg_cast];
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs;
 
 	relation = table_open(CastRelationId, RowExclusiveLock);
 
@@ -83,32 +84,29 @@ CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, char castcontext,
 
 	CatalogTupleInsert(relation, tuple);
 
+	addrs = new_object_addresses();
+
 	/* make dependency entries */
-	myself.classId = CastRelationId;
-	myself.objectId = castid;
-	myself.objectSubId = 0;
+	ObjectAddressSet(myself, CastRelationId, castid);
 
 	/* dependency on source type */
-	referenced.classId = TypeRelationId;
-	referenced.objectId = sourcetypeid;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, behavior);
+	ObjectAddressSet(referenced, TypeRelationId, sourcetypeid);
+	add_exact_object_address(&referenced, addrs);
 
 	/* dependency on target type */
-	referenced.classId = TypeRelationId;
-	referenced.objectId = targettypeid;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, behavior);
+	ObjectAddressSet(referenced, TypeRelationId, targettypeid);
+	add_exact_object_address(&referenced, addrs);
 
 	/* dependency on function */
 	if (OidIsValid(funcid))
 	{
-		referenced.classId = ProcedureRelationId;
-		referenced.objectId = funcid;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, behavior);
+		ObjectAddressSet(referenced, ProcedureRelationId, funcid);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, behavior);
+	free_object_addresses(addrs);
+
 	/* dependency on extension */
 	recordDependencyOnCurrentExtension(&myself, false);
 
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index fdc63e7dea..5ec2df12d3 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -91,6 +91,8 @@ CreateConstraintEntry(const char *constraintName,
 	NameData	cname;
 	int			i;
 	ObjectAddress conobject;
+	ObjectAddresses *addrs_auto;
+	ObjectAddresses *addrs_normal;
 
 	conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
 
@@ -227,6 +229,9 @@ CreateConstraintEntry(const char *constraintName,
 
 	table_close(conDesc, RowExclusiveLock);
 
+	/* Handle set of auto dependencies */
+	addrs_auto = new_object_addresses();
+
 	if (OidIsValid(relId))
 	{
 		/*
@@ -241,13 +246,13 @@ CreateConstraintEntry(const char *constraintName,
 			{
 				ObjectAddressSubSet(relobject, RelationRelationId, relId,
 									constraintKey[i]);
-				recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO);
+				add_exact_object_address(&relobject, addrs_auto);
 			}
 		}
 		else
 		{
 			ObjectAddressSet(relobject, RelationRelationId, relId);
-			recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO);
+			add_exact_object_address(&relobject, addrs_auto);
 		}
 	}
 
@@ -259,9 +264,16 @@ CreateConstraintEntry(const char *constraintName,
 		ObjectAddress domobject;
 
 		ObjectAddressSet(domobject, TypeRelationId, domainId);
-		recordDependencyOn(&conobject, &domobject, DEPENDENCY_AUTO);
+		add_exact_object_address(&domobject, addrs_auto);
 	}
 
+	record_object_address_dependencies(&conobject, addrs_auto,
+									   DEPENDENCY_AUTO);
+	free_object_addresses(addrs_auto);
+
+	/* Handle set if normal dependencies */
+	addrs_normal = new_object_addresses();
+
 	if (OidIsValid(foreignRelId))
 	{
 		/*
@@ -276,13 +288,13 @@ CreateConstraintEntry(const char *constraintName,
 			{
 				ObjectAddressSubSet(relobject, RelationRelationId,
 									foreignRelId, foreignKey[i]);
-				recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+				add_exact_object_address(&relobject, addrs_normal);
 			}
 		}
 		else
 		{
 			ObjectAddressSet(relobject, RelationRelationId, foreignRelId);
-			recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+			add_exact_object_address(&relobject, addrs_normal);
 		}
 	}
 
@@ -297,7 +309,7 @@ CreateConstraintEntry(const char *constraintName,
 		ObjectAddress relobject;
 
 		ObjectAddressSet(relobject, RelationRelationId, indexRelId);
-		recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+		add_exact_object_address(&relobject, addrs_normal);
 	}
 
 	if (foreignNKeys > 0)
@@ -316,20 +328,24 @@ CreateConstraintEntry(const char *constraintName,
 		for (i = 0; i < foreignNKeys; i++)
 		{
 			oprobject.objectId = pfEqOp[i];
-			recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+			add_exact_object_address(&oprobject, addrs_normal);
 			if (ppEqOp[i] != pfEqOp[i])
 			{
 				oprobject.objectId = ppEqOp[i];
-				recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+				add_exact_object_address(&oprobject, addrs_normal);
 			}
 			if (ffEqOp[i] != pfEqOp[i])
 			{
 				oprobject.objectId = ffEqOp[i];
-				recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+				add_exact_object_address(&oprobject, addrs_normal);
 			}
 		}
 	}
 
+	record_object_address_dependencies(&conobject, addrs_normal,
+									   DEPENDENCY_NORMAL);
+	free_object_addresses(addrs_normal);
+
 	/*
 	 * We don't bother to register dependencies on the exclusion operators of
 	 * an exclusion constraint.  We assume they are members of the opclass
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 65a36be5ee..f7c07c9b5b 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -775,6 +775,7 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
 	Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple);
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs;
 
 	ObjectAddressSet(myself, OperatorRelationId, oper->oid);
 
@@ -788,32 +789,34 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
 		deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
 	}
 
+	addrs = new_object_addresses();
+
 	/* Dependency on namespace */
 	if (OidIsValid(oper->oprnamespace))
 	{
 		ObjectAddressSet(referenced, NamespaceRelationId, oper->oprnamespace);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Dependency on left type */
 	if (OidIsValid(oper->oprleft))
 	{
 		ObjectAddressSet(referenced, TypeRelationId, oper->oprleft);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Dependency on right type */
 	if (OidIsValid(oper->oprright))
 	{
 		ObjectAddressSet(referenced, TypeRelationId, oper->oprright);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Dependency on result type */
 	if (OidIsValid(oper->oprresult))
 	{
 		ObjectAddressSet(referenced, TypeRelationId, oper->oprresult);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/*
@@ -829,23 +832,26 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
 	if (OidIsValid(oper->oprcode))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, oper->oprcode);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Dependency on restriction selectivity function */
 	if (OidIsValid(oper->oprrest))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, oper->oprrest);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* Dependency on join selectivity function */
 	if (OidIsValid(oper->oprjoin))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, oper->oprjoin);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
+
 	/* Dependency on owner */
 	recordDependencyOnOwner(OperatorRelationId, oper->oid,
 							oper->oprowner);
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index a28ab74d60..40d65dc6ba 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -114,6 +114,7 @@ ProcedureCreate(const char *procedureName,
 	char	   *detailmsg;
 	int			i;
 	Oid			trfid;
+	ObjectAddresses *addrs;
 
 	/*
 	 * sanity checks
@@ -585,53 +586,58 @@ ProcedureCreate(const char *procedureName,
 	if (is_update)
 		deleteDependencyRecordsFor(ProcedureRelationId, retval, true);
 
+	addrs = new_object_addresses();
+
 	ObjectAddressSet(myself, ProcedureRelationId, retval);
 
 	/* dependency on namespace */
 	ObjectAddressSet(referenced, NamespaceRelationId, procNamespace);
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	add_exact_object_address(&referenced, addrs);
 
 	/* dependency on implementation language */
 	ObjectAddressSet(referenced, LanguageRelationId, languageObjectId);
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	add_exact_object_address(&referenced, addrs);
 
 	/* dependency on return type */
 	ObjectAddressSet(referenced, TypeRelationId, returnType);
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	add_exact_object_address(&referenced, addrs);
 
 	/* dependency on transform used by return type, if any */
 	if ((trfid = get_transform_oid(returnType, languageObjectId, true)))
 	{
 		ObjectAddressSet(referenced, TransformRelationId, trfid);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* dependency on parameter types */
 	for (i = 0; i < allParamCount; i++)
 	{
 		ObjectAddressSet(referenced, TypeRelationId, allParams[i]);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 
 		/* dependency on transform used by parameter type, if any */
 		if ((trfid = get_transform_oid(allParams[i], languageObjectId, true)))
 		{
 			ObjectAddressSet(referenced, TransformRelationId, trfid);
-			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+			add_exact_object_address(&referenced, addrs);
 		}
 	}
 
-	/* dependency on parameter default expressions */
-	if (parameterDefaults)
-		recordDependencyOnExpr(&myself, (Node *) parameterDefaults,
-							   NIL, DEPENDENCY_NORMAL);
-
 	/* dependency on support function, if any */
 	if (OidIsValid(prosupport))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, prosupport);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
+
+	/* dependency on parameter default expressions */
+	if (parameterDefaults)
+		recordDependencyOnExpr(&myself, (Node *) parameterDefaults,
+							   NIL, DEPENDENCY_NORMAL);
+
 	/* dependency on owner */
 	if (!is_update)
 		recordDependencyOnOwner(ProcedureRelationId, retval, proowner);
diff --git a/src/backend/catalog/pg_range.c b/src/backend/catalog/pg_range.c
index b5bc36c2bd..a606d8c3ad 100644
--- a/src/backend/catalog/pg_range.c
+++ b/src/backend/catalog/pg_range.c
@@ -43,6 +43,7 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
 	HeapTuple	tup;
 	ObjectAddress myself;
 	ObjectAddress referenced;
+	ObjectAddresses *addrs;
 
 	pg_range = table_open(RangeRelationId, RowExclusiveLock);
 
@@ -61,45 +62,37 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
 	heap_freetuple(tup);
 
 	/* record type's dependencies on range-related items */
+	addrs = new_object_addresses();
 
-	myself.classId = TypeRelationId;
-	myself.objectId = rangeTypeOid;
-	myself.objectSubId = 0;
+	ObjectAddressSet(myself, TypeRelationId, rangeTypeOid);
 
-	referenced.classId = TypeRelationId;
-	referenced.objectId = rangeSubType;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(referenced, TypeRelationId, rangeSubType);
+	add_exact_object_address(&referenced, addrs);
 
-	referenced.classId = OperatorClassRelationId;
-	referenced.objectId = rangeSubOpclass;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(referenced, OperatorClassRelationId, rangeSubOpclass);
+	add_exact_object_address(&referenced, addrs);
 
 	if (OidIsValid(rangeCollation))
 	{
-		referenced.classId = CollationRelationId;
-		referenced.objectId = rangeCollation;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(referenced, CollationRelationId, rangeCollation);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	if (OidIsValid(rangeCanonical))
 	{
-		referenced.classId = ProcedureRelationId;
-		referenced.objectId = rangeCanonical;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(referenced, ProcedureRelationId, rangeCanonical);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	if (OidIsValid(rangeSubDiff))
 	{
-		referenced.classId = ProcedureRelationId;
-		referenced.objectId = rangeSubDiff;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(referenced, ProcedureRelationId, rangeSubDiff);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
+
 	table_close(pg_range, RowExclusiveLock);
 }
 
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 79ffe317dd..ba83efb505 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -554,6 +554,7 @@ GenerateTypeDependencies(HeapTuple typeTuple,
 	bool		isNull;
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs_normal;
 
 	/* Extract defaultExpr if caller didn't pass it */
 	if (defaultExpr == NULL)
@@ -587,6 +588,10 @@ GenerateTypeDependencies(HeapTuple typeTuple,
 	 * Skip these for a dependent type, since it will have such dependencies
 	 * indirectly through its depended-on type or relation.
 	 */
+
+	/* placeholder for all normal dependencies */
+	addrs_normal = new_object_addresses();
+
 	if (!isDependentType)
 	{
 		ObjectAddressSet(referenced, NamespaceRelationId,
@@ -606,45 +611,68 @@ GenerateTypeDependencies(HeapTuple typeTuple,
 	if (OidIsValid(typeForm->typinput))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typinput);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs_normal);
 	}
 
 	if (OidIsValid(typeForm->typoutput))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typoutput);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs_normal);
 	}
 
 	if (OidIsValid(typeForm->typreceive))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typreceive);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs_normal);
 	}
 
 	if (OidIsValid(typeForm->typsend))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsend);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs_normal);
 	}
 
 	if (OidIsValid(typeForm->typmodin))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodin);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs_normal);
 	}
 
 	if (OidIsValid(typeForm->typmodout))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodout);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs_normal);
 	}
 
 	if (OidIsValid(typeForm->typanalyze))
 	{
 		ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typanalyze);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs_normal);
 	}
 
+	/* Normal dependency from a domain to its base type. */
+	if (OidIsValid(typeForm->typbasetype))
+	{
+		ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
+		add_exact_object_address(&referenced, addrs_normal);
+	}
+
+	/* Normal dependency from a domain to its collation. */
+	/* We know the default collation is pinned, so don't bother recording it */
+	if (OidIsValid(typeForm->typcollation) &&
+		typeForm->typcollation != DEFAULT_COLLATION_OID)
+	{
+		ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
+		add_exact_object_address(&referenced, addrs_normal);
+	}
+
+	record_object_address_dependencies(&myself, addrs_normal, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs_normal);
+
+	/* Normal dependency on the default expression. */
+	if (defaultExpr)
+		recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
+
 	/*
 	 * If the type is a rowtype for a relation, mark it as internally
 	 * dependent on the relation, *unless* it is a stand-alone composite type
@@ -675,26 +703,6 @@ GenerateTypeDependencies(HeapTuple typeTuple,
 		recordDependencyOn(&myself, &referenced,
 						   isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
 	}
-
-	/* Normal dependency from a domain to its base type. */
-	if (OidIsValid(typeForm->typbasetype))
-	{
-		ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-	}
-
-	/* Normal dependency from a domain to its collation. */
-	/* We know the default collation is pinned, so don't bother recording it */
-	if (OidIsValid(typeForm->typcollation) &&
-		typeForm->typcollation != DEFAULT_COLLATION_OID)
-	{
-		ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-	}
-
-	/* Normal dependency on the default expression. */
-	if (defaultExpr)
-		recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
 }
 
 /*
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 1b5bdcec8b..e236581a8e 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1696,6 +1696,7 @@ CreateTransform(CreateTransformStmt *stmt)
 	Relation	relation;
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs;
 	bool		is_replace;
 
 	/*
@@ -1836,39 +1837,34 @@ CreateTransform(CreateTransformStmt *stmt)
 	if (is_replace)
 		deleteDependencyRecordsFor(TransformRelationId, transformid, true);
 
+	addrs = new_object_addresses();
+
 	/* make dependency entries */
-	myself.classId = TransformRelationId;
-	myself.objectId = transformid;
-	myself.objectSubId = 0;
+	ObjectAddressSet(myself, TransformRelationId, transformid);
 
 	/* dependency on language */
-	referenced.classId = LanguageRelationId;
-	referenced.objectId = langid;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(referenced, LanguageRelationId, langid);
+	add_exact_object_address(&referenced, addrs);
 
 	/* dependency on type */
-	referenced.classId = TypeRelationId;
-	referenced.objectId = typeid;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(referenced, TypeRelationId, typeid);
+	add_exact_object_address(&referenced, addrs);
 
 	/* dependencies on functions */
 	if (OidIsValid(fromsqlfuncid))
 	{
-		referenced.classId = ProcedureRelationId;
-		referenced.objectId = fromsqlfuncid;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
+		add_exact_object_address(&referenced, addrs);
 	}
 	if (OidIsValid(tosqlfuncid))
 	{
-		referenced.classId = ProcedureRelationId;
-		referenced.objectId = tosqlfuncid;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
+
 	/* dependency on extension */
 	recordDependencyOnCurrentExtension(&myself, is_replace);
 
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 14153426bd..8ef60374f5 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -57,6 +57,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	bool		is_update;
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs;
 
 	/*
 	 * Check permission
@@ -186,30 +187,29 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	/* dependency on extension */
 	recordDependencyOnCurrentExtension(&myself, is_update);
 
+	addrs = new_object_addresses();
+
 	/* dependency on the PL handler function */
-	referenced.classId = ProcedureRelationId;
-	referenced.objectId = handlerOid;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(referenced, ProcedureRelationId, handlerOid);
+	add_exact_object_address(&referenced, addrs);
 
 	/* dependency on the inline handler function, if any */
 	if (OidIsValid(inlineOid))
 	{
-		referenced.classId = ProcedureRelationId;
-		referenced.objectId = inlineOid;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(referenced, ProcedureRelationId, inlineOid);
+		add_exact_object_address(&referenced, addrs);
 	}
 
 	/* dependency on the validator function, if any */
 	if (OidIsValid(valOid))
 	{
-		referenced.classId = ProcedureRelationId;
-		referenced.objectId = valOid;
-		referenced.objectSubId = 0;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		ObjectAddressSet(referenced, ProcedureRelationId, valOid);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
+
 	/* Post creation hook for new procedural language */
 	InvokeObjectPostCreateHook(LanguageRelationId, myself.objectId, 0);
 
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 319a62012e..f5d1d137b8 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -133,42 +133,41 @@ makeParserDependencies(HeapTuple tuple)
 	Form_pg_ts_parser prs = (Form_pg_ts_parser) GETSTRUCT(tuple);
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs;
 
-	myself.classId = TSParserRelationId;
-	myself.objectId = prs->oid;
-	myself.objectSubId = 0;
-
-	/* dependency on namespace */
-	referenced.classId = NamespaceRelationId;
-	referenced.objectId = prs->prsnamespace;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(myself, TSParserRelationId, prs->oid);
 
 	/* dependency on extension */
 	recordDependencyOnCurrentExtension(&myself, false);
 
-	/* dependencies on functions */
-	referenced.classId = ProcedureRelationId;
-	referenced.objectSubId = 0;
+	addrs = new_object_addresses();
 
-	referenced.objectId = prs->prsstart;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	/* dependency on namespace */
+	ObjectAddressSet(referenced, NamespaceRelationId, prs->prsnamespace);
+	add_exact_object_address(&referenced, addrs);
+
+	/* dependencies on functions */
+	ObjectAddressSet(referenced, ProcedureRelationId, prs->prsstart);
+	add_exact_object_address(&referenced, addrs);
 
 	referenced.objectId = prs->prstoken;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	add_exact_object_address(&referenced, addrs);
 
 	referenced.objectId = prs->prsend;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	add_exact_object_address(&referenced, addrs);
 
 	referenced.objectId = prs->prslextype;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	add_exact_object_address(&referenced, addrs);
 
 	if (OidIsValid(prs->prsheadline))
 	{
 		referenced.objectId = prs->prsheadline;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
+
 	return myself;
 }
 
@@ -304,16 +303,9 @@ makeDictionaryDependencies(HeapTuple tuple)
 	Form_pg_ts_dict dict = (Form_pg_ts_dict) GETSTRUCT(tuple);
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs;
 
-	myself.classId = TSDictionaryRelationId;
-	myself.objectId = dict->oid;
-	myself.objectSubId = 0;
-
-	/* dependency on namespace */
-	referenced.classId = NamespaceRelationId;
-	referenced.objectId = dict->dictnamespace;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(myself, TSDictionaryRelationId, dict->oid);
 
 	/* dependency on owner */
 	recordDependencyOnOwner(myself.classId, myself.objectId, dict->dictowner);
@@ -321,11 +313,18 @@ makeDictionaryDependencies(HeapTuple tuple)
 	/* dependency on extension */
 	recordDependencyOnCurrentExtension(&myself, false);
 
+	addrs = new_object_addresses();
+
+	/* dependency on namespace */
+	ObjectAddressSet(referenced, NamespaceRelationId, dict->dictnamespace);
+	add_exact_object_address(&referenced, addrs);
+
 	/* dependency on template */
-	referenced.classId = TSTemplateRelationId;
-	referenced.objectId = dict->dicttemplate;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(referenced, TSTemplateRelationId, dict->dicttemplate);
+	add_exact_object_address(&referenced, addrs);
+
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
 
 	return myself;
 }
@@ -649,33 +648,32 @@ makeTSTemplateDependencies(HeapTuple tuple)
 	Form_pg_ts_template tmpl = (Form_pg_ts_template) GETSTRUCT(tuple);
 	ObjectAddress myself,
 				referenced;
+	ObjectAddresses *addrs;
 
-	myself.classId = TSTemplateRelationId;
-	myself.objectId = tmpl->oid;
-	myself.objectSubId = 0;
-
-	/* dependency on namespace */
-	referenced.classId = NamespaceRelationId;
-	referenced.objectId = tmpl->tmplnamespace;
-	referenced.objectSubId = 0;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	ObjectAddressSet(myself, TSTemplateRelationId, tmpl->oid);
 
 	/* dependency on extension */
 	recordDependencyOnCurrentExtension(&myself, false);
 
-	/* dependencies on functions */
-	referenced.classId = ProcedureRelationId;
-	referenced.objectSubId = 0;
+	addrs = new_object_addresses();
 
-	referenced.objectId = tmpl->tmpllexize;
-	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	/* dependency on namespace */
+	ObjectAddressSet(referenced, NamespaceRelationId, tmpl->tmplnamespace);
+	add_exact_object_address(&referenced, addrs);
+
+	/* dependencies on functions */
+	ObjectAddressSet(referenced, ProcedureRelationId, tmpl->tmpllexize);
+	add_exact_object_address(&referenced, addrs);
 
 	if (OidIsValid(tmpl->tmplinit))
 	{
 		referenced.objectId = tmpl->tmplinit;
-		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		add_exact_object_address(&referenced, addrs);
 	}
 
+	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+	free_object_addresses(addrs);
+
 	return myself;
 }
 
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index e3e6634d7e..814416d936 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2069,11 +2069,10 @@ WHERE classid = 'pg_class'::regclass AND
  index concur_reindex_ind3                | column c1 of table concur_reindex_tab                      | a
  index concur_reindex_ind3                | table concur_reindex_tab                                   | a
  index concur_reindex_ind4                | column c1 of table concur_reindex_tab                      | a
- index concur_reindex_ind4                | column c1 of table concur_reindex_tab                      | a
  index concur_reindex_ind4                | column c2 of table concur_reindex_tab                      | a
  materialized view concur_reindex_matview | schema public                                              | n
  table concur_reindex_tab                 | schema public                                              | n
-(9 rows)
+(8 rows)
 
 REINDEX INDEX CONCURRENTLY concur_reindex_ind1;
 REINDEX TABLE CONCURRENTLY concur_reindex_tab;
@@ -2097,11 +2096,10 @@ WHERE classid = 'pg_class'::regclass AND
  index concur_reindex_ind3                | column c1 of table concur_reindex_tab                      | a
  index concur_reindex_ind3                | table concur_reindex_tab                                   | a
  index concur_reindex_ind4                | column c1 of table concur_reindex_tab                      | a
- index concur_reindex_ind4                | column c1 of table concur_reindex_tab                      | a
  index concur_reindex_ind4                | column c2 of table concur_reindex_tab                      | a
  materialized view concur_reindex_matview | schema public                                              | n
  table concur_reindex_tab                 | schema public                                              | n
-(9 rows)
+(8 rows)
 
 -- Check that comments are preserved
 CREATE TABLE testcomment (i int);
-- 
2.28.0

Attachment: signature.asc
Description: PGP signature

Reply via email to