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

📄 pg_shdepend.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
									   sdepForm->deptype, 0);		}		else if (sdepForm->dbid == InvalidOid)		{			numSharedDeps++;			if (++totalDeps <= MAX_REPORTED_DEPS)				storeObjectDescription(&descs, SHARED_OBJECT, &object,									   sdepForm->deptype, 0);		}		else		{			/* It's not local nor shared, so it must be remote. */			remoteDep  *dep;			bool		stored = false;			/*			 * XXX this info is kept on a simple List.	Maybe it's not good			 * for performance, but using a hash table seems needlessly			 * complex.  The expected number of databases is not high anyway,			 * I suppose.			 */			foreach(cell, remDeps)			{				dep = lfirst(cell);				if (dep->dbOid == sdepForm->dbid)				{					dep->count++;					stored = true;					break;				}			}			if (!stored)			{				dep = (remoteDep *) palloc(sizeof(remoteDep));				dep->dbOid = sdepForm->dbid;				dep->count = 1;				remDeps = lappend(remDeps, dep);				totalDeps++;			}		}	}	systable_endscan(scan);	heap_close(sdepRel, AccessShareLock);	if (totalDeps > MAX_REPORTED_DEPS)	{		/*		 * Report seems unreasonably long, so reduce it to per-database info		 *		 * Note: we don't ever suppress per-database totals, which should be		 * OK as long as there aren't too many databases ...		 */		descs.len = 0;			/* reset to empty */		descs.data[0] = '\0';		if (numLocalDeps > 0)		{			appendStringInfo(&descs, _("%d objects in this database"),							 numLocalDeps);			if (numSharedDeps > 0)				appendStringInfoChar(&descs, '\n');		}		if (numSharedDeps > 0)			appendStringInfo(&descs, _("%d shared objects"),							 numSharedDeps);	}	foreach(cell, remDeps)	{		remoteDep  *dep = lfirst(cell);		object.classId = DatabaseRelationId;		object.objectId = dep->dbOid;		object.objectSubId = 0;		storeObjectDescription(&descs, REMOTE_OBJECT, &object,							   SHARED_DEPENDENCY_INVALID, dep->count);	}	list_free_deep(remDeps);	if (descs.len == 0)	{		pfree(descs.data);		return NULL;	}	return descs.data;}/* * copyTemplateDependencies * * Routine to create the initial shared dependencies of a new database. * We simply copy the dependencies from the template database. */voidcopyTemplateDependencies(Oid templateDbId, Oid newDbId){	Relation	sdepRel;	TupleDesc	sdepDesc;	ScanKeyData key[1];	SysScanDesc scan;	HeapTuple	tup;	CatalogIndexState indstate;	Datum		values[Natts_pg_shdepend];	bool		nulls[Natts_pg_shdepend];	bool		replace[Natts_pg_shdepend];	sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);	sdepDesc = RelationGetDescr(sdepRel);	indstate = CatalogOpenIndexes(sdepRel);	/* Scan all entries with dbid = templateDbId */	ScanKeyInit(&key[0],				Anum_pg_shdepend_dbid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(templateDbId));	scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,							  SnapshotNow, 1, key);	/* Set up to copy the tuples except for inserting newDbId */	memset(values, 0, sizeof(values));	memset(nulls, false, sizeof(nulls));	memset(replace, false, sizeof(replace));	replace[Anum_pg_shdepend_dbid - 1] = true;	values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId);	/*	 * Copy the entries of the original database, changing the database Id to	 * that of the new database.  Note that because we are not copying rows	 * with dbId == 0 (ie, rows describing dependent shared objects) we won't	 * copy the ownership dependency of the template database itself; this is	 * what we want.	 */	while (HeapTupleIsValid(tup = systable_getnext(scan)))	{		HeapTuple	newtup;		newtup = heap_modify_tuple(tup, sdepDesc, values, nulls, replace);		simple_heap_insert(sdepRel, newtup);		/* Keep indexes current */		CatalogIndexInsert(indstate, newtup);		heap_freetuple(newtup);	}	systable_endscan(scan);	CatalogCloseIndexes(indstate);	heap_close(sdepRel, RowExclusiveLock);}/* * dropDatabaseDependencies * * Delete pg_shdepend entries corresponding to a database that's being * dropped. */voiddropDatabaseDependencies(Oid databaseId){	Relation	sdepRel;	ScanKeyData key[1];	SysScanDesc scan;	HeapTuple	tup;	sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);	/*	 * First, delete all the entries that have the database Oid in the dbid	 * field.	 */	ScanKeyInit(&key[0],				Anum_pg_shdepend_dbid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(databaseId));	/* We leave the other index fields unspecified */	scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,							  SnapshotNow, 1, key);	while (HeapTupleIsValid(tup = systable_getnext(scan)))	{		simple_heap_delete(sdepRel, &tup->t_self);	}	systable_endscan(scan);	/* Now delete all entries corresponding to the database itself */	shdepDropDependency(sdepRel, DatabaseRelationId, databaseId,						InvalidOid, InvalidOid,						SHARED_DEPENDENCY_INVALID);	heap_close(sdepRel, RowExclusiveLock);}/* * deleteSharedDependencyRecordsFor * * Delete all pg_shdepend entries corresponding to an object that's being * dropped or modified.  The object is assumed to be either a shared object * or local to the current database (the classId tells us which). */voiddeleteSharedDependencyRecordsFor(Oid classId, Oid objectId){	Relation	sdepRel;	sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);	shdepDropDependency(sdepRel, classId, objectId,						InvalidOid, InvalidOid,						SHARED_DEPENDENCY_INVALID);	heap_close(sdepRel, RowExclusiveLock);}/* * shdepAddDependency *		Internal workhorse for inserting into pg_shdepend * * sdepRel must be the pg_shdepend relation, already opened and suitably * locked. */static voidshdepAddDependency(Relation sdepRel, Oid classId, Oid objectId,				   Oid refclassId, Oid refobjId,				   SharedDependencyType deptype){	HeapTuple	tup;	Datum		values[Natts_pg_shdepend];	bool		nulls[Natts_pg_shdepend];	/*	 * Make sure the object doesn't go away while we record the dependency on	 * it.	DROP routines should lock the object exclusively before they check	 * shared dependencies.	 */	shdepLockAndCheckObject(refclassId, refobjId);	memset(nulls, false, sizeof(nulls));	/*	 * Form the new tuple and record the dependency.	 */	values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));	values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);	values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);	values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);	values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);	values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);	tup = heap_form_tuple(sdepRel->rd_att, values, nulls);	simple_heap_insert(sdepRel, tup);	/* keep indexes current */	CatalogUpdateIndexes(sdepRel, tup);	/* clean up */	heap_freetuple(tup);}/* * shdepDropDependency *		Internal workhorse for deleting entries from pg_shdepend. * * We drop entries having the following properties: *	dependent object is the one identified by classId/objectId *	if refclassId isn't InvalidOid, it must match the entry's refclassid *	if refobjId isn't InvalidOid, it must match the entry's refobjid *	if deptype isn't SHARED_DEPENDENCY_INVALID, it must match entry's deptype * * sdepRel must be the pg_shdepend relation, already opened and suitably * locked. */static voidshdepDropDependency(Relation sdepRel, Oid classId, Oid objectId,					Oid refclassId, Oid refobjId,					SharedDependencyType deptype){	ScanKeyData key[3];	SysScanDesc scan;	HeapTuple	tup;	/* Scan for entries matching the dependent object */	ScanKeyInit(&key[0],				Anum_pg_shdepend_dbid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(classIdGetDbId(classId)));	ScanKeyInit(&key[1],				Anum_pg_shdepend_classid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(classId));	ScanKeyInit(&key[2],				Anum_pg_shdepend_objid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(objectId));	scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,							  SnapshotNow, 3, key);	while (HeapTupleIsValid(tup = systable_getnext(scan)))	{		Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);		/* Filter entries according to additional parameters */		if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)			continue;		if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)			continue;		if (deptype != SHARED_DEPENDENCY_INVALID &&			shdepForm->deptype != deptype)			continue;		/* OK, delete it */		simple_heap_delete(sdepRel, &tup->t_self);	}	systable_endscan(scan);}/* * classIdGetDbId * * Get the database Id that should be used in pg_shdepend, given the OID * of the catalog containing the object.  For shared objects, it's 0 * (InvalidOid); for all other objects, it's the current database Id. * * XXX it's awfully tempting to hard-wire this instead of doing a syscache * lookup ... but resist the temptation, unless you can prove it's a * bottleneck. */static OidclassIdGetDbId(Oid classId){	Oid			dbId;	HeapTuple	tup;	tup = SearchSysCache(RELOID,						 ObjectIdGetDatum(classId),						 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for relation %u", classId);	if (((Form_pg_class) GETSTRUCT(tup))->relisshared)		dbId = InvalidOid;	else		dbId = MyDatabaseId;	ReleaseSysCache(tup);	return dbId;}/* * shdepLockAndCheckObject * * Lock the object that we are about to record a dependency on. * After it's locked, verify that it hasn't been dropped while we * weren't looking.  If the object has been dropped, this function * does not return! */static voidshdepLockAndCheckObject(Oid classId, Oid objectId){	/* AccessShareLock should be OK, since we are not modifying the object */	LockSharedObject(classId, objectId, 0, AccessShareLock);	/*	 * We have to recognize sinval updates here, else our local syscache may	 * still contain the object even if it was just dropped.	 */	AcceptInvalidationMessages();	switch (classId)	{		case AuthIdRelationId:			if (!SearchSysCacheExists(AUTHOID,									  ObjectIdGetDatum(objectId),									  0, 0, 0))				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_OBJECT),						 errmsg("role %u was concurrently dropped",								objectId)));			break;			/*			 * Currently, this routine need not support any other shared			 * object types besides roles.	If we wanted to record explicit			 * dependencies on databases or tablespaces, we'd need code along			 * these lines:			 */#ifdef NOT_USED		case TableSpaceRelationId:			{				/* For lack of a syscache on pg_tablespace, do this: */				char	   *tablespace = get_tablespace_name(objectId);				if (tablespace == NULL)					ereport(ERROR,							(errcode(ERRCODE_UNDEFINED_OBJECT),							 errmsg("tablespace %u was concurrently dropped",									objectId)));				pfree(tablespace);				break;			}#endif		default:			elog(ERROR, "unrecognized shared classId: %u", classId);	}}/* * storeObjectDescription *		Append the description of a dependent object to "descs" * * While searching for dependencies of a shared object, we stash the * descriptions of dependent objects we find in a single string, which we * later pass to ereport() in the DETAIL field when somebody attempts to * drop a referenced shared object. * * When type is LOCAL_OBJECT or SHARED_OBJECT, we expect object to be the * dependent object, deptype is the dependency type, and count is not used. * When type is REMOTE_OBJECT, we expect object to be the database object, * and count to be nonzero; deptype is not used in this case. */static voidstoreObjectDescription(StringInfo descs, objectType type,					   ObjectAddress *object,					   SharedDependencyType deptype,					   int count){	char	   *objdesc = getObjectDescription(object);	/* separate entries with a newline */	if (descs->len != 0)		appendStringInfoChar(descs, '\n');	switch (type)	{		case LOCAL_OBJECT:		case SHARED_OBJECT:			if (deptype == SHARED_DEPENDENCY_OWNER)				appendStringInfo(descs, _("owner of %s"), objdesc);			else if (deptype == SHARED_DEPENDENCY_ACL)				appendStringInfo(descs, _("access to %s"), objdesc);			else				elog(ERROR, "unrecognized dependency type: %d",					 (int) deptype);			break;		case REMOTE_OBJECT:			/* translator: %s will always be "database %s" */			appendStringInfo(descs, _("%d objects in %s"), count, objdesc);			break;		default:			elog(ERROR, "unrecognized object type: %d", type);	}	pfree(objdesc);}/* * isSharedObjectPinned *		Return whether a given shared object has a SHARED_DEPENDENCY_PIN entry. * * sdepRel must be the pg_shdepend relation, already opened and suitably * locked. */static boolisSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel){	bool		result = false;	ScanKeyData key[2];	SysScanDesc scan;	HeapTuple	tup;	ScanKeyInit(&key[0],				Anum_pg_shdepend_refclassid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(classId));	ScanKeyInit(&key[1],				Anum_pg_shdepend_refobjid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(objectId));	scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,							  SnapshotNow, 2, key);	/*	 * Since we won't generate additional pg_shdepend 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_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);		if (shdepForm->deptype == SHARED_DEPENDENCY_PIN)			result = true;	}	systable_endscan(scan);	return result;}

⌨️ 快捷键说明

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