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

📄 heap.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* ----------------	 *	create a scan key to locate the type tuple corresponding	 *	to this relation.	 * ----------------	 */	ScanKeyEntryInitialize(&key, 0,						   Anum_pg_type_typrelid,						   F_OIDEQ,						   ObjectIdGetDatum(RelationGetRelid(rel)));	pg_type_scan = heap_beginscan(pg_type_desc,								  0,								  SnapshotNow,								  1,								  &key);	/* ----------------	 *	use heap_getnext() to fetch the pg_type tuple.	If this	 *	tuple is not valid then something's wrong.	 * ----------------	 */	tup = heap_getnext(pg_type_scan, 0);	if (!HeapTupleIsValid(tup))	{		heap_endscan(pg_type_scan);		heap_close(pg_type_desc);		elog(ERROR, "DeleteTypeTuple: %s type nonexistent",			 &rel->rd_rel->relname);	}	/* ----------------	 *	now scan pg_attribute.	if any other relations have	 *	attributes of the type of the relation we are deleteing	 *	then we have to disallow the deletion.	should talk to	 *	stonebraker about this.  -cim 6/19/90	 * ----------------	 */	typoid = tup->t_data->t_oid;	pg_attribute_desc = heap_openr(AttributeRelationName);	ScanKeyEntryInitialize(&attkey,						   0,						   Anum_pg_attribute_atttypid,						   F_OIDEQ,						   typoid);	pg_attribute_scan = heap_beginscan(pg_attribute_desc,									   0,									   SnapshotNow,									   1,									   &attkey);	/* ----------------	 *	try and get a pg_attribute tuple.  if we succeed it means	 *	we can't delete the relation because something depends on	 *	the schema.	 * ----------------	 */	atttup = heap_getnext(pg_attribute_scan, 0);	if (HeapTupleIsValid(atttup))	{		Oid			relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;		heap_endscan(pg_type_scan);		heap_close(pg_type_desc);		heap_endscan(pg_attribute_scan);		heap_close(pg_attribute_desc);		elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",			 &rel->rd_rel->relname, relid);	}	heap_endscan(pg_attribute_scan);	heap_close(pg_attribute_desc);	/* ----------------	 *	Ok, it's safe so we delete the relation tuple	 *	from pg_type and finish up.  But first end the scan so that	 *	we release the read lock on pg_type.  -mer 13 Aug 1991	 * ----------------	 */	heap_delete(pg_type_desc, &tup->t_self, NULL);	heap_endscan(pg_type_scan);	heap_close(pg_type_desc);}/* -------------------------------- *		heap_destroy_with_catalog * * -------------------------------- */voidheap_destroy_with_catalog(char *relname){	Relation	rel;	Oid			rid;	bool		istemp = (get_temp_rel_by_name(relname) != NULL);	/* ----------------	 *	first open the relation.  if the relation does exist,	 *	heap_openr() returns NULL.	 * ----------------	 */	rel = heap_openr(relname);	if (rel == NULL)		elog(ERROR, "Relation '%s' does not exist", relname);	LockRelation(rel, AccessExclusiveLock);	rid = rel->rd_id;	/* ----------------	 *	prevent deletion of system relations	 * ----------------	 */	/* allow temp of pg_class? Guess so. */	if (!istemp &&		!allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)->data))		elog(ERROR, "System relation '%s' cannot be destroyed",			 &rel->rd_rel->relname);	/* ----------------	 *	remove inheritance information	 * ----------------	 */	RelationRemoveInheritance(rel);	/* ----------------	 *	remove indexes if necessary	 * ----------------	 */	if (rel->rd_rel->relhasindex)		RelationRemoveIndexes(rel);	/* ----------------	 *	remove rules if necessary	 * ----------------	 */	if (rel->rd_rules != NULL)		RelationRemoveRules(rid);	/* triggers */	if (rel->rd_rel->reltriggers > 0)		RelationRemoveTriggers(rel);	/* ----------------	 *	delete attribute tuples	 * ----------------	 */	DeleteAttributeTuples(rel);	if (istemp)		remove_temp_relation(rid);	/* ----------------	 *	delete type tuple.	here we want to see the effects	 *	of the deletions we just did, so we use setheapoverride().	 * ----------------	 */	setheapoverride(true);	DeleteTypeTuple(rel);	setheapoverride(false);	/* ----------------	 *	delete relation tuple	 * ----------------	 */	/* must delete fake tuple in cache */	DeleteRelationTuple(rel);	/*	 * release dirty buffers of this relation	 */	ReleaseRelationBuffers(rel);	/* ----------------	 *	flush the relation from the relcache	 * ----------------	 * Does nothing!!! Flushing moved below.	- vadim 06/04/97	RelationIdInvalidateRelationCacheByRelationId(rel->rd_id);	 */	RemoveConstraints(rel);	/* ----------------	 *	unlink the relation and finish up.	 * ----------------	 */	if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))		smgrunlink(DEFAULT_SMGR, rel);	rel->rd_nonameunlinked = TRUE;	UnlockRelation(rel, AccessExclusiveLock);	heap_close(rel);	RelationForgetRelation(rid);}/* * heap_destroy *	  destroy and close temporary relations * */voidheap_destroy(Relation rel){	ReleaseRelationBuffers(rel);	if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))		smgrunlink(DEFAULT_SMGR, rel);	rel->rd_nonameunlinked = TRUE;	heap_close(rel);	RemoveFromNoNameRelList(rel);}/**************************************************************  functions to deal with the list of temporary relations**************************************************************//* --------------   InitTempRellist():   initialize temporary relations list   the tempRelList is a list of temporary relations that   are created in the course of the transactions   they need to be destroyed properly at the end of the transactions   MODIFIES the global variable tempRels >> NOTE <<   malloc is used instead of palloc because we KNOW when we are   going to free these things.	Keeps us away from the memory context   hairyness*/voidInitNoNameRelList(void){	if (tempRels)	{		free(tempRels->rels);		free(tempRels);	}	tempRels = (TempRelList *) malloc(sizeof(TempRelList));	tempRels->size = NONAME_REL_LIST_SIZE;	tempRels->rels = (Relation *) malloc(sizeof(Relation) * tempRels->size);	MemSet(tempRels->rels, 0, sizeof(Relation) * tempRels->size);	tempRels->num = 0;}/*   removes a relation from the TempRelList   MODIFIES the global variable tempRels	  we don't really remove it, just mark it as NULL	  and DestroyNoNameRels will look for NULLs*/static voidRemoveFromNoNameRelList(Relation r){	int			i;	if (!tempRels)		return;	for (i = 0; i < tempRels->num; i++)	{		if (tempRels->rels[i] == r)		{			tempRels->rels[i] = NULL;			break;		}	}}/*   add a temporary relation to the TempRelList   MODIFIES the global variable tempRels*/static voidAddToNoNameRelList(Relation r){	if (!tempRels)		return;	if (tempRels->num == tempRels->size)	{		tempRels->size += NONAME_REL_LIST_SIZE;		tempRels->rels = realloc(tempRels->rels,								 sizeof(Relation) * tempRels->size);	}	tempRels->rels[tempRels->num] = r;	tempRels->num++;}/*   go through the tempRels list and destroy each of the relations*/voidDestroyNoNameRels(void){	int			i;	Relation	rel;	if (!tempRels)		return;	for (i = 0; i < tempRels->num; i++)	{		rel = tempRels->rels[i];		/* rel may be NULL if it has been removed from the list already */		if (rel)			heap_destroy(rel);	}	free(tempRels->rels);	free(tempRels);	tempRels = NULL;}static voidStoreAttrDefault(Relation rel, AttrDefault *attrdef){	char		str[MAX_PARSE_BUFFER];	char		cast[2 * NAMEDATALEN] = {0};	Form_pg_attribute atp = rel->rd_att->attrs[attrdef->adnum - 1];	List	   *queryTree_list;	List	   *planTree_list;	Query	   *query;	TargetEntry *te;	Resdom	   *resdom;	Node	   *expr;	Oid			type;	char	   *adbin;	MemoryContext oldcxt;	Relation	adrel;	Relation	idescs[Num_pg_attrdef_indices];	HeapTuple	tuple;	Datum		values[4];	char		nulls[4] = {' ', ' ', ' ', ' '};	extern GlobalMemory CacheCxt;start:	/*	 * Surround table name with double quotes to allow mixed-case and	 * whitespaces in names. - BGA 1998-11-14	 */	snprintf(str, MAX_PARSE_BUFFER,			 "select %s%s from \"%.*s\"", attrdef->adsrc, cast,			 NAMEDATALEN, rel->rd_rel->relname.data);	setheapoverride(true);	planTree_list = pg_parse_and_plan(str, NULL, 0,									  &queryTree_list, None, FALSE);	setheapoverride(false);	query = (Query *) lfirst(queryTree_list);	if (length(query->rtable) > 1 ||		flatten_tlist(query->targetList) != NIL)		elog(ERROR, "Cannot use attribute(s) in DEFAULT clause");	te = (TargetEntry *) lfirst(query->targetList);	resdom = te->resdom;	expr = te->expr;	type = exprType(expr);	if (type != atp->atttypid)	{		if (IS_BINARY_COMPATIBLE(type, atp->atttypid))			;					/* use without change */		else if (can_coerce_type(1, &(type), &(atp->atttypid)))			expr = coerce_type(NULL, (Node *) expr, type, atp->atttypid,							   atp->atttypmod);		else if (IsA(expr, Const))		{			if (*cast != 0)				elog(ERROR, "DEFAULT clause const type '%s' mismatched with column type '%s'",					 typeidTypeName(type), typeidTypeName(atp->atttypid));			snprintf(cast, 2 * NAMEDATALEN, ":: %s", typeidTypeName(atp->atttypid));			goto start;		}		else			elog(ERROR, "DEFAULT clause type '%s' mismatched with column type '%s'",				 typeidTypeName(type), typeidTypeName(atp->atttypid));	}	adbin = nodeToString(expr);	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);	attrdef->adbin = pstrdup(adbin);	(void) MemoryContextSwitchTo(oldcxt);	pfree(adbin);	values[Anum_pg_attrdef_adrelid - 1] = rel->rd_id;	values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum;	values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin));	values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc));	adrel = heap_openr(AttrDefaultRelationName);	tuple = heap_formtuple(adrel->rd_att, values, nulls);	CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs);	heap_insert(adrel, tuple);	CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);	CatalogCloseIndices(Num_pg_attrdef_indices, idescs);	heap_close(adrel);	pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));	pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));	pfree(tuple);}static voidStoreRelCheck(Relation rel, ConstrCheck *check){	char		str[MAX_PARSE_BUFFER];	List	   *queryTree_list;	List	   *planTree_list;	Query	   *query;	Plan	   *plan;	List	   *qual;	char	   *ccbin;	MemoryContext oldcxt;	Relation	rcrel;	Relation	idescs[Num_pg_relcheck_indices];	HeapTuple	tuple;	Datum		values[4];	char		nulls[4] = {' ', ' ', ' ', ' '};	extern GlobalMemory CacheCxt;	/*	 * Check for table's existance. Surround table name with double-quotes	 * to allow mixed-case and whitespace names. - thomas 1998-11-12	 */	snprintf(str, MAX_PARSE_BUFFER,			 "select 1 from \"%.*s\" where %s",			 NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc);	setheapoverride(true);	planTree_list = pg_parse_and_plan(str, NULL, 0,									  &queryTree_list, None, FALSE);	setheapoverride(false);	query = (Query *) lfirst(queryTree_list);	if (length(query->rtable) > 1)		elog(ERROR, "Only relation '%.*s' can be referenced",			 NAMEDATALEN, rel->rd_rel->relname.data);	plan = (Plan *) lfirst(planTree_list);	qual = plan->qual;	ccbin = nodeToString(qual);	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);	check->ccbin = (char *) palloc(strlen(ccbin) + 1);	strcpy(check->ccbin, ccbin);	(void) MemoryContextSwitchTo(oldcxt);	pfree(ccbin);	values[Anum_pg_relcheck_rcrelid - 1] = rel->rd_id;	values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(check->ccname));	values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin));	values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc));	rcrel = heap_openr(RelCheckRelationName);	tuple = heap_formtuple(rcrel->rd_att, values, nulls);	CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs);	heap_insert(rcrel, tuple);	CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);	CatalogCloseIndices(Num_pg_relcheck_indices, idescs);	heap_close(rcrel);	pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));	pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));	pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));	pfree(tuple);	return;}static voidStoreConstraints(Relation rel){	TupleConstr *constr = rel->rd_att->constr;	int			i;	if (!constr)		return;	if (constr->num_defval > 0)	{		for (i = 0; i < constr->num_defval; i++)			StoreAttrDefault(rel, &(constr->defval[i]));	}	if (constr->num_check > 0)	{		for (i = 0; i < constr->num_check; i++)			StoreRelCheck(rel, &(constr->check[i]));	}	return;}static voidRemoveAttrDefault(Relation rel){	Relation	adrel;	HeapScanDesc adscan;	ScanKeyData key;	HeapTuple	tup;	adrel = heap_openr(AttrDefaultRelationName);	ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,						   F_OIDEQ, rel->rd_id);	LockRelation(adrel, AccessExclusiveLock);	adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);	while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))		heap_delete(adrel, &tup->t_self, NULL);	heap_endscan(adscan);	UnlockRelation(adrel, AccessExclusiveLock);	heap_close(adrel);}static voidRemoveRelCheck(Relation rel){	Relation	rcrel;	HeapScanDesc rcscan;	ScanKeyData key;	HeapTuple	tup;	rcrel = heap_openr(RelCheckRelationName);	ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,						   F_OIDEQ, rel->rd_id);	LockRelation(rcrel, AccessExclusiveLock);	rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);	while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))		heap_delete(rcrel, &tup->t_self, NULL);	heap_endscan(rcscan);	UnlockRelation(rcrel, AccessExclusiveLock);	heap_close(rcrel);}static voidRemoveConstraints(Relation rel){	TupleConstr *constr = rel->rd_att->constr;	if (!constr)		return;	if (constr->num_defval > 0)		RemoveAttrDefault(rel);	if (constr->num_check > 0)		RemoveRelCheck(rel);	return;}

⌨️ 快捷键说明

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