recordMultipleDependencies(const ObjectAddress *depender,
						   const ObjectAddress *referenced,
						   int nreferenced,
						   DependencyType behavior)
{
	Relation	dependDesc;
	CatalogIndexState indstate;
	TupleTableSlot **slot;
	int			i,
				max_slots,
				slot_init_count,
				slot_stored_count;

	if (nreferenced <= 0)
		return;					/* nothing to do */

	/*
	 * During bootstrap, do nothing since pg_depend may not exist yet. initdb
	 * will fill in appropriate pg_depend entries after bootstrap.
	 */
	if (IsBootstrapProcessingMode())
		return;

	dependDesc = table_open(DependRelationId, RowExclusiveLock);

	/*
	 * Allocate the slots to use, but delay costly initialization until we
	 * know that they will be used.
	 */
	max_slots = Min(nreferenced,
					MAX_CATALOG_MULTI_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;

	/* number of slots currently storing tuples */
	slot_stored_count = 0;
	/* number of slots currently initialized */
	slot_init_count = 0;
	for (i = 0; i < nreferenced; i++, referenced++)
	{
		/*
		 * If the referenced object is pinned by the system, there's no real
		 * 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))
			continue;

		if (slot_init_count < max_slots)
		{
			slot[slot_stored_count] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc),
															   &TTSOpsHeapTuple);
			slot_init_count++;
		}

		ExecClearTuple(slot[slot_stored_count]);

		/*
		 * Record the dependency.  Note we don't bother to check for duplicate
		 * dependencies; there's no harm in them.
		 */
		slot[slot_stored_count]->tts_values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
		slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
		slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
		slot[slot_stored_count]->tts_values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
		slot[slot_stored_count]->tts_values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
		slot[slot_stored_count]->tts_values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
		slot[slot_stored_count]->tts_values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);

		memset(slot[slot_stored_count]->tts_isnull, false,
			   slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));

		ExecStoreVirtualTuple(slot[slot_stored_count]);
		slot_stored_count++;

		/* If slots are full, insert a batch of tuples */
		if (slot_stored_count == max_slots)
		{
			/* fetch index info only when we know we need it */
			if (indstate == NULL)
				indstate = CatalogOpenIndexes(dependDesc);

			CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count,
											 indstate);
			slot_stored_count = 0;
		}
	}

	/* Insert any tuples left in the buffer */
	if (slot_stored_count > 0)
	{
		/* fetch index info only when we know we need it */
		if (indstate == NULL)
			indstate = CatalogOpenIndexes(dependDesc);

		CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count,
										 indstate);
	}

	if (indstate != NULL)
		CatalogCloseIndexes(indstate);

	table_close(dependDesc, RowExclusiveLock);

	/* Drop only the number of slots used */
	for (i = 0; i < slot_init_count; i++)
		ExecDropSingleTupleTableSlot(slot[i]);
	pfree(slot);
}