⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pg_depend.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
字号:
/*------------------------------------------------------------------------- * * pg_depend.c *	  routines to support manipulation of the pg_depend relation * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.15 2005/10/15 02:49:14 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/heapam.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_open(DependRelationId, 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_open(DependRelationId, RowExclusiveLock);	ScanKeyInit(&key[0],				Anum_pg_depend_classid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(classId));	ScanKeyInit(&key[1],				Anum_pg_depend_objid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(objectId));	scan = systable_beginscan(depRel, DependDependerIndexId, 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;}/* * Adjust dependency record(s) to point to a different object of the same type * * classId/objectId specify the referencing object. * refClassId/oldRefObjectId specify the old referenced object. * newRefObjectId is the new referenced object (must be of class refClassId). * * Note the lack of objsubid parameters.  If there are subobject references * they will all be readjusted. * * Returns the number of records updated. */longchangeDependencyFor(Oid classId, Oid objectId,					Oid refClassId, Oid oldRefObjectId,					Oid newRefObjectId){	long		count = 0;	Relation	depRel;	ScanKeyData key[2];	SysScanDesc scan;	HeapTuple	tup;	ObjectAddress objAddr;	bool		newIsPinned;	depRel = heap_open(DependRelationId, RowExclusiveLock);	/*	 * If oldRefObjectId is pinned, there won't be any dependency entries on	 * it --- we can't cope in that case.  (This isn't really worth expending	 * code to fix, in current usage; it just means you can't rename stuff out	 * of pg_catalog, which would likely be a bad move anyway.)	 */	objAddr.classId = refClassId;	objAddr.objectId = oldRefObjectId;	objAddr.objectSubId = 0;	if (isObjectPinned(&objAddr, depRel))		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),		errmsg("cannot remove dependency on %s because it is a system object",			   getObjectDescription(&objAddr))));	/*	 * We can handle adding a dependency on something pinned, though, since	 * that just means deleting the dependency entry.	 */	objAddr.objectId = newRefObjectId;	newIsPinned = isObjectPinned(&objAddr, depRel);	/* Now search for dependency records */	ScanKeyInit(&key[0],				Anum_pg_depend_classid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(classId));	ScanKeyInit(&key[1],				Anum_pg_depend_objid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(objectId));	scan = systable_beginscan(depRel, DependDependerIndexId, true,							  SnapshotNow, 2, key);	while (HeapTupleIsValid((tup = systable_getnext(scan))))	{		Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);		if (depform->refclassid == refClassId &&			depform->refobjid == oldRefObjectId)		{			if (newIsPinned)				simple_heap_delete(depRel, &tup->t_self);			else			{				/* make a modifiable copy */				tup = heap_copytuple(tup);				depform = (Form_pg_depend) GETSTRUCT(tup);				depform->refobjid = newRefObjectId;				simple_heap_update(depRel, &tup->t_self, tup);				CatalogUpdateIndexes(depRel, tup);				heap_freetuple(tup);			}			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];	ScanKeyInit(&key[0],				Anum_pg_depend_refclassid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(object->classId));	ScanKeyInit(&key[1],				Anum_pg_depend_refobjid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(object->objectId));	scan = systable_beginscan(rel, DependReferenceIndexId, 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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -