pg_depend.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 211 行

C
211
字号
/*------------------------------------------------------------------------- * * pg_depend.c *	  routines to support manipulation of the pg_depend relation * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.7 2003/08/04 02:39:58 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/heapam.h"#include "catalog/catname.h"#include "catalog/indexing.h"#include "catalog/dependency.h"#include "catalog/pg_depend.h"#include "miscadmin.h"#include "utils/fmgroids.h"static bool isObjectPinned(const ObjectAddress *object, Relation rel);/* * Record a dependency between 2 objects via their respective objectAddress. * The first argument is the dependent object, the second the one it * references. * * This simply creates an entry in pg_depend, without any other processing. */voidrecordDependencyOn(const ObjectAddress *depender,				   const ObjectAddress *referenced,				   DependencyType behavior){	recordMultipleDependencies(depender, referenced, 1, behavior);}/* * Record multiple dependencies (of the same kind) for a single dependent * object.	This has a little less overhead than recording each separately. */voidrecordMultipleDependencies(const ObjectAddress *depender,						   const ObjectAddress *referenced,						   int nreferenced,						   DependencyType behavior){	Relation	dependDesc;	CatalogIndexState indstate;	HeapTuple	tup;	int			i;	char		nulls[Natts_pg_depend];	Datum		values[Natts_pg_depend];	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 = heap_openr(DependRelationName, RowExclusiveLock);	/* Don't open indexes unless we need to make an update */	indstate = NULL;	memset(nulls, ' ', sizeof(nulls));	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))		{			/*			 * 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_formtuple(dependDesc->rd_att, values, nulls);			simple_heap_insert(dependDesc, tup);			/* keep indexes current */			if (indstate == NULL)				indstate = CatalogOpenIndexes(dependDesc);			CatalogIndexInsert(indstate, tup);			heap_freetuple(tup);		}	}	if (indstate != NULL)		CatalogCloseIndexes(indstate);	heap_close(dependDesc, RowExclusiveLock);}/* * deleteDependencyRecordsFor -- delete all records with given depender * classId/objectId.  Returns the number of records deleted. * * This is used when redefining an existing object.  Links leading to the * object do not change, and links leading from it will be recreated * (possibly with some differences from before). */longdeleteDependencyRecordsFor(Oid classId, Oid objectId){	long		count = 0;	Relation	depRel;	ScanKeyData key[2];	SysScanDesc scan;	HeapTuple	tup;	depRel = heap_openr(DependRelationName, RowExclusiveLock);	ScanKeyEntryInitialize(&key[0], 0x0,						   Anum_pg_depend_classid, F_OIDEQ,						   ObjectIdGetDatum(classId));	ScanKeyEntryInitialize(&key[1], 0x0,						   Anum_pg_depend_objid, F_OIDEQ,						   ObjectIdGetDatum(objectId));	scan = systable_beginscan(depRel, DependDependerIndex, true,							  SnapshotNow, 2, key);	while (HeapTupleIsValid(tup = systable_getnext(scan)))	{		simple_heap_delete(depRel, &tup->t_self);		count++;	}	systable_endscan(scan);	heap_close(depRel, RowExclusiveLock);	return count;}/* * isObjectPinned() * * Test if an object is required for basic database functionality. * Caller must already have opened pg_depend. * * The passed subId, if any, is ignored; we assume that only whole objects * are pinned (and that this implies pinning their components). */static boolisObjectPinned(const ObjectAddress *object, Relation rel){	bool		ret = false;	SysScanDesc scan;	HeapTuple	tup;	ScanKeyData key[2];	ScanKeyEntryInitialize(&key[0], 0x0,						   Anum_pg_depend_refclassid, F_OIDEQ,						   ObjectIdGetDatum(object->classId));	ScanKeyEntryInitialize(&key[1], 0x0,						   Anum_pg_depend_refobjid, F_OIDEQ,						   ObjectIdGetDatum(object->objectId));	scan = systable_beginscan(rel, DependReferenceIndex, true,							  SnapshotNow, 2, key);	/*	 * Since we won't generate additional pg_depend entries for pinned	 * objects, there can be at most one entry referencing a pinned	 * object.	Hence, it's sufficient to look at the first returned	 * tuple; we don't need to loop.	 */	tup = systable_getnext(scan);	if (HeapTupleIsValid(tup))	{		Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);		if (foundDep->deptype == DEPENDENCY_PIN)			ret = true;	}	systable_endscan(scan);	return ret;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?