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

📄 heap.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
		object.objectSubId = 0;		performDeletion(&object, behavior);		found = true;	}	systable_endscan(scan);	heap_close(attrdef_rel, RowExclusiveLock);	if (complain && !found)		elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",			 relid, attnum);}/* *		RemoveAttrDefaultById * * Remove a pg_attrdef entry specified by OID.	This is the guts of * attribute-default removal.  Note it should be called via performDeletion, * not directly. */voidRemoveAttrDefaultById(Oid attrdefId){	Relation	attrdef_rel;	Relation	attr_rel;	Relation	myrel;	ScanKeyData scankeys[1];	SysScanDesc scan;	HeapTuple	tuple;	Oid			myrelid;	AttrNumber	myattnum;	/* Grab an appropriate lock on the pg_attrdef relation */	attrdef_rel = heap_open(AttrDefaultRelationId, RowExclusiveLock);	/* Find the pg_attrdef tuple */	ScanKeyInit(&scankeys[0],				ObjectIdAttributeNumber,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(attrdefId));	scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,							  SnapshotNow, 1, scankeys);	tuple = systable_getnext(scan);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "could not find tuple for attrdef %u", attrdefId);	myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;	myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;	/* Get an exclusive lock on the relation owning the attribute */	myrel = relation_open(myrelid, AccessExclusiveLock);	/* Now we can delete the pg_attrdef row */	simple_heap_delete(attrdef_rel, &tuple->t_self);	systable_endscan(scan);	heap_close(attrdef_rel, RowExclusiveLock);	/* Fix the pg_attribute row */	attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);	tuple = SearchSysCacheCopy(ATTNUM,							   ObjectIdGetDatum(myrelid),							   Int16GetDatum(myattnum),							   0, 0);	if (!HeapTupleIsValid(tuple))		/* shouldn't happen */		elog(ERROR, "cache lookup failed for attribute %d of relation %u",			 myattnum, myrelid);	((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;	simple_heap_update(attr_rel, &tuple->t_self, tuple);	/* keep the system catalog indexes current */	CatalogUpdateIndexes(attr_rel, tuple);	/*	 * Our update of the pg_attribute row will force a relcache rebuild, so	 * there's nothing else to do here.	 */	heap_close(attr_rel, RowExclusiveLock);	/* Keep lock on attribute's rel until end of xact */	relation_close(myrel, NoLock);}/* * heap_drop_with_catalog	- removes specified relation from catalogs * * Note that this routine is not responsible for dropping objects that are * linked to the pg_class entry via dependencies (for example, indexes and * constraints).  Those are deleted by the dependency-tracing logic in * dependency.c before control gets here.  In general, therefore, this routine * should never be called directly; go through performDeletion() instead. */voidheap_drop_with_catalog(Oid relid){	Relation	rel;	/*	 * Open and lock the relation.	 */	rel = relation_open(relid, AccessExclusiveLock);	/*	 * Schedule unlinking of the relation's physical file at commit.	 */	if (rel->rd_rel->relkind != RELKIND_VIEW &&		rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)	{		RelationOpenSmgr(rel);		smgrscheduleunlink(rel->rd_smgr, rel->rd_istemp);	}	/*	 * Close relcache entry, but *keep* AccessExclusiveLock on the relation	 * until transaction commit.  This ensures no one else will try to do	 * something with the doomed relation.	 */	relation_close(rel, NoLock);	/*	 * Forget any ON COMMIT action for the rel	 */	remove_on_commit_action(relid);	/*	 * Flush the relation from the relcache.  We want to do this before	 * starting to remove catalog entries, just to be certain that no relcache	 * entry rebuild will happen partway through.  (That should not really	 * matter, since we don't do CommandCounterIncrement here, but let's be	 * safe.)	 */	RelationForgetRelation(relid);	/*	 * remove inheritance information	 */	RelationRemoveInheritance(relid);	/*	 * delete statistics	 */	RemoveStatistics(relid, 0);	/*	 * delete attribute tuples	 */	DeleteAttributeTuples(relid);	/*	 * delete relation tuple	 */	DeleteRelationTuple(relid);}/* * Store a default expression for column attnum of relation rel. * The expression must be presented as a nodeToString() string. */voidStoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin){	Node	   *expr;	char	   *adsrc;	Relation	adrel;	HeapTuple	tuple;	Datum		values[4];	static char nulls[4] = {' ', ' ', ' ', ' '};	Relation	attrrel;	HeapTuple	atttup;	Form_pg_attribute attStruct;	Oid			attrdefOid;	ObjectAddress colobject,				defobject;	/*	 * Need to construct source equivalent of given node-string.	 */	expr = stringToNode(adbin);	/*	 * deparse it	 */	adsrc = deparse_expression(expr,							deparse_context_for(RelationGetRelationName(rel),												RelationGetRelid(rel)),							   false, false);	/*	 * Make the pg_attrdef entry.	 */	values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);	values[Anum_pg_attrdef_adnum - 1] = attnum;	values[Anum_pg_attrdef_adbin - 1] = DirectFunctionCall1(textin,													 CStringGetDatum(adbin));	values[Anum_pg_attrdef_adsrc - 1] = DirectFunctionCall1(textin,													 CStringGetDatum(adsrc));	adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock);	tuple = heap_formtuple(adrel->rd_att, values, nulls);	attrdefOid = simple_heap_insert(adrel, tuple);	CatalogUpdateIndexes(adrel, tuple);	defobject.classId = AttrDefaultRelationId;	defobject.objectId = attrdefOid;	defobject.objectSubId = 0;	heap_close(adrel, RowExclusiveLock);	/* now can free some of the stuff allocated above */	pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));	pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));	heap_freetuple(tuple);	pfree(adsrc);	/*	 * Update the pg_attribute entry for the column to show that a default	 * exists.	 */	attrrel = heap_open(AttributeRelationId, RowExclusiveLock);	atttup = SearchSysCacheCopy(ATTNUM,								ObjectIdGetDatum(RelationGetRelid(rel)),								Int16GetDatum(attnum),								0, 0);	if (!HeapTupleIsValid(atttup))		elog(ERROR, "cache lookup failed for attribute %d of relation %u",			 attnum, RelationGetRelid(rel));	attStruct = (Form_pg_attribute) GETSTRUCT(atttup);	if (!attStruct->atthasdef)	{		attStruct->atthasdef = true;		simple_heap_update(attrrel, &atttup->t_self, atttup);		/* keep catalog indexes current */		CatalogUpdateIndexes(attrrel, atttup);	}	heap_close(attrrel, RowExclusiveLock);	heap_freetuple(atttup);	/*	 * Make a dependency so that the pg_attrdef entry goes away if the column	 * (or whole table) is deleted.	 */	colobject.classId = RelationRelationId;	colobject.objectId = RelationGetRelid(rel);	colobject.objectSubId = attnum;	recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);	/*	 * Record dependencies on objects used in the expression, too.	 */	recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);}/* * Store a check-constraint expression for the given relation. * The expression must be presented as a nodeToString() string. * * Caller is responsible for updating the count of constraints * in the pg_class entry for the relation. */static voidStoreRelCheck(Relation rel, char *ccname, char *ccbin){	Node	   *expr;	char	   *ccsrc;	List	   *varList;	int			keycount;	int16	   *attNos;	/*	 * Convert condition to an expression tree.	 */	expr = stringToNode(ccbin);	/*	 * deparse it	 */	ccsrc = deparse_expression(expr,							deparse_context_for(RelationGetRelationName(rel),												RelationGetRelid(rel)),							   false, false);	/*	 * Find columns of rel that are used in ccbin	 *	 * NB: pull_var_clause is okay here only because we don't allow subselects	 * in check constraints; it would fail to examine the contents of	 * subselects.	 */	varList = pull_var_clause(expr, false);	keycount = list_length(varList);	if (keycount > 0)	{		ListCell   *vl;		int			i = 0;		attNos = (int16 *) palloc(keycount * sizeof(int16));		foreach(vl, varList)		{			Var		   *var = (Var *) lfirst(vl);			int			j;			for (j = 0; j < i; j++)				if (attNos[j] == var->varattno)					break;			if (j == i)				attNos[i++] = var->varattno;		}		keycount = i;	}	else		attNos = NULL;	/*	 * Create the Check Constraint	 */	CreateConstraintEntry(ccname,		/* Constraint Name */						  RelationGetNamespace(rel),	/* namespace */						  CONSTRAINT_CHECK,		/* Constraint Type */						  false,	/* Is Deferrable */						  false,	/* Is Deferred */						  RelationGetRelid(rel),		/* relation */						  attNos,		/* attrs in the constraint */						  keycount,		/* # attrs in the constraint */						  InvalidOid,	/* not a domain constraint */						  InvalidOid,	/* Foreign key fields */						  NULL,						  0,						  ' ',						  ' ',						  ' ',						  InvalidOid,	/* no associated index */						  expr, /* Tree form check constraint */						  ccbin,	/* Binary form check constraint */						  ccsrc);		/* Source form check constraint */	pfree(ccsrc);}/* * Store defaults and constraints passed in via the tuple constraint struct. * * NOTE: only pre-cooked expressions will be passed this way, which is to * say expressions inherited from an existing relation.  Newly parsed * expressions can be added later, by direct calls to StoreAttrDefault * and StoreRelCheck (see AddRelationRawConstraints()). */static voidStoreConstraints(Relation rel, TupleDesc tupdesc){	TupleConstr *constr = tupdesc->constr;	int			i;	if (!constr)		return;					/* nothing to do */	/*	 * Deparsing of constraint expressions will fail unless the just-created	 * pg_attribute tuples for this relation are made visible.	So, bump the	 * command counter.  CAUTION: this will cause a relcache entry rebuild.	 */	CommandCounterIncrement();	for (i = 0; i < constr->num_defval; i++)		StoreAttrDefault(rel, constr->defval[i].adnum,						 constr->defval[i].adbin);	for (i = 0; i < constr->num_check; i++)		StoreRelCheck(rel, constr->check[i].ccname,					  constr->check[i].ccbin);	if (constr->num_check > 0)		SetRelationNumChecks(rel, constr->num_check);}/* * AddRelationRawConstraints * * Add raw (not-yet-transformed) column default expressions and/or constraint * check expressions to an existing relation.  This is defined to do both * for efficiency in DefineRelation, but of course you can do just one or * the other by passing empty lists. * * rel: relation to be modified * rawColDefaults: list of RawColumnDefault structures * rawConstraints: list of Constraint nodes * * All entries in rawColDefaults will be processed.  Entries in rawConstraints * will be processed only if they are CONSTR_CHECK type and contain a "raw" * expression. * * Returns a list of CookedConstraint nodes that shows the cooked form of * the default and constraint expressions added to the relation. * * NB: caller should have opened rel with AccessExclusiveLock, and should * hold that lock till end of transaction.	Also, we assume the caller has * done a CommandCounterIncrement if necessary to make the relation's catalog * tuples visible. */List *AddRelationRawConstraints(Relation rel,						  List *rawColDefaults,						  List *rawConstraints){	List	   *cookedConstraints = NIL;	TupleDesc	tupleDesc;	TupleConstr *oldconstr;	int			numoldchecks;	ParseState *pstate;	RangeTblEntry *rte;	int			numchecks;	List	   *checknames;	ListCell   *cell;	Node	   *expr;	CookedConstraint *cooked;	/*	 * Get info about existing constraints.	 */	tupleDesc = RelationGetDescr(rel);	oldconstr = tupleDesc->constr;	if (oldconstr)		numoldchecks = oldconstr->num_check;	else		numoldchecks = 0;	/*	 * Create a dummy ParseState and insert the target relation as its sole	 * rangetable entry.  We need a ParseState for transformExpr.	 */	pstate = make_parsestate(NULL);	rte = addRangeTableEntryForRelation(pstate,										rel,										NULL,										false,										true);	addRTEtoQuery(pstate, rte, true, true, true);	/*	 * Process column default expressions.	 */	foreach(cell, rawColDefaults)	{		RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);		Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];		expr = cookDefault(pstate, colDef->raw_default,						   atp->atttypid, atp->atttypmod,						   NameStr(atp->attname));		StoreAttrDefault(rel, colDef->attnum, nodeToString(expr));		cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));		cooked->contype = CONSTR_DEFAULT;		cooked->name = NULL;		cooked->attnum = colDef->attnum;		cooked->expr = expr;		cookedConstraints = lappend(cookedConstraints, cooked);	}	/*	 * Process constraint expressions.	 */	numchecks = numoldchecks;	checknames = NIL;	foreach(cell, rawConstraints)	{		Constraint *cdef = (Constraint *) lfirst(cell);		char	   *ccname;		if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL)			continue;		Assert(cdef->cooked_expr == NULL);		/*		 * Transform raw parsetree to executable expression.		 */		expr = transformExpr(pstate, cdef->raw_expr);		/*		 * Make sure it yields a boolean result.		 */		expr = coerce_to_boolean(pstate, expr, "CHECK");		/*		 * Make sure no outside relations are referred to.		 */		if (list_length(pstate->p_rtable) != 1)			ereport(ERROR,					(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),			errmsg("only table \"%s\" can be referenced in check constraint",				   RelationGetRelationName(rel))));		/*		 * No subplans or aggregates, either...		 */		if (pstate->p_hasSubLinks)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("cannot use subquery in check constraint")));		if (pstate->p_hasAggs)			ereport(ERROR,					(errcode(ERRCODE_GROUPING_ERROR),			   errmsg("cannot use aggregate function in check constraint")));		/*		 * Check name uniqueness, or generate a name if none was given.		 */		if (cdef->name != NULL)		{

⌨️ 快捷键说明

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