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

📄 relcache.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		relation->rd_att->attrs[0]->attcacheoff = 0;	/*	 * Set up constraint/default info	 */	if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)	{		relation->rd_att->constr = constr;		if (ndef > 0)			/* DEFAULTs */		{			if (ndef < relation->rd_rel->relnatts)				constr->defval = (AttrDefault *)					repalloc(attrdef, ndef * sizeof(AttrDefault));			else				constr->defval = attrdef;			constr->num_defval = ndef;			AttrDefaultFetch(relation);		}		else			constr->num_defval = 0;		if (relation->rd_rel->relchecks > 0)	/* CHECKs */		{			constr->num_check = relation->rd_rel->relchecks;			constr->check = (ConstrCheck *)				MemoryContextAllocZero(CacheMemoryContext,									constr->num_check * sizeof(ConstrCheck));			CheckConstraintFetch(relation);		}		else			constr->num_check = 0;	}	else	{		pfree(constr);		relation->rd_att->constr = NULL;	}}/* *		RelationBuildRuleLock * *		Form the relation's rewrite rules from information in *		the pg_rewrite system catalog. * * Note: The rule parsetrees are potentially very complex node structures. * To allow these trees to be freed when the relcache entry is flushed, * we make a private memory context to hold the RuleLock information for * each relcache entry that has associated rules.  The context is used * just for rule info, not for any other subsidiary data of the relcache * entry, because that keeps the update logic in RelationClearRelation() * manageable.	The other subsidiary data structures are simple enough * to be easy to free explicitly, anyway. */static voidRelationBuildRuleLock(Relation relation){	MemoryContext rulescxt;	MemoryContext oldcxt;	HeapTuple	rewrite_tuple;	Relation	rewrite_desc;	TupleDesc	rewrite_tupdesc;	SysScanDesc rewrite_scan;	ScanKeyData key;	RuleLock   *rulelock;	int			numlocks;	RewriteRule **rules;	int			maxlocks;	/*	 * Make the private context.  Parameters are set on the assumption that	 * it'll probably not contain much data.	 */	rulescxt = AllocSetContextCreate(CacheMemoryContext,									 RelationGetRelationName(relation),									 ALLOCSET_SMALL_MINSIZE,									 ALLOCSET_SMALL_INITSIZE,									 ALLOCSET_SMALL_MAXSIZE);	relation->rd_rulescxt = rulescxt;	/*	 * allocate an array to hold the rewrite rules (the array is extended if	 * necessary)	 */	maxlocks = 4;	rules = (RewriteRule **)		MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);	numlocks = 0;	/*	 * form a scan key	 */	ScanKeyInit(&key,				Anum_pg_rewrite_ev_class,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(RelationGetRelid(relation)));	/*	 * open pg_rewrite and begin a scan	 *	 * Note: since we scan the rules using RewriteRelRulenameIndexId, we will	 * be reading the rules in name order, except possibly during	 * emergency-recovery operations (ie, IsIgnoringSystemIndexes). This in	 * turn ensures that rules will be fired in name order.	 */	rewrite_desc = heap_open(RewriteRelationId, AccessShareLock);	rewrite_tupdesc = RelationGetDescr(rewrite_desc);	rewrite_scan = systable_beginscan(rewrite_desc,									  RewriteRelRulenameIndexId,									  true, SnapshotNow,									  1, &key);	while (HeapTupleIsValid(rewrite_tuple = systable_getnext(rewrite_scan)))	{		Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);		bool		isnull;		Datum		ruleaction;		Datum		rule_evqual;		char	   *ruleaction_str;		char	   *rule_evqual_str;		RewriteRule *rule;		rule = (RewriteRule *) MemoryContextAlloc(rulescxt,												  sizeof(RewriteRule));		rule->ruleId = HeapTupleGetOid(rewrite_tuple);		rule->event = rewrite_form->ev_type - '0';		rule->attrno = rewrite_form->ev_attr;		rule->isInstead = rewrite_form->is_instead;		/* Must use heap_getattr to fetch ev_qual and ev_action */		ruleaction = heap_getattr(rewrite_tuple,								  Anum_pg_rewrite_ev_action,								  rewrite_tupdesc,								  &isnull);		Assert(!isnull);		ruleaction_str = DatumGetCString(DirectFunctionCall1(textout,															 ruleaction));		oldcxt = MemoryContextSwitchTo(rulescxt);		rule->actions = (List *) stringToNode(ruleaction_str);		MemoryContextSwitchTo(oldcxt);		pfree(ruleaction_str);		rule_evqual = heap_getattr(rewrite_tuple,								   Anum_pg_rewrite_ev_qual,								   rewrite_tupdesc,								   &isnull);		Assert(!isnull);		rule_evqual_str = DatumGetCString(DirectFunctionCall1(textout,															  rule_evqual));		oldcxt = MemoryContextSwitchTo(rulescxt);		rule->qual = (Node *) stringToNode(rule_evqual_str);		MemoryContextSwitchTo(oldcxt);		pfree(rule_evqual_str);		if (numlocks >= maxlocks)		{			maxlocks *= 2;			rules = (RewriteRule **)				repalloc(rules, sizeof(RewriteRule *) * maxlocks);		}		rules[numlocks++] = rule;	}	/*	 * end the scan and close the attribute relation	 */	systable_endscan(rewrite_scan);	heap_close(rewrite_desc, AccessShareLock);	/*	 * form a RuleLock and insert into relation	 */	rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));	rulelock->numLocks = numlocks;	rulelock->rules = rules;	relation->rd_rules = rulelock;}/* *		equalRuleLocks * *		Determine whether two RuleLocks are equivalent * *		Probably this should be in the rules code someplace... */static boolequalRuleLocks(RuleLock *rlock1, RuleLock *rlock2){	int			i;	/*	 * As of 7.3 we assume the rule ordering is repeatable, because	 * RelationBuildRuleLock should read 'em in a consistent order.  So just	 * compare corresponding slots.	 */	if (rlock1 != NULL)	{		if (rlock2 == NULL)			return false;		if (rlock1->numLocks != rlock2->numLocks)			return false;		for (i = 0; i < rlock1->numLocks; i++)		{			RewriteRule *rule1 = rlock1->rules[i];			RewriteRule *rule2 = rlock2->rules[i];			if (rule1->ruleId != rule2->ruleId)				return false;			if (rule1->event != rule2->event)				return false;			if (rule1->attrno != rule2->attrno)				return false;			if (rule1->isInstead != rule2->isInstead)				return false;			if (!equal(rule1->qual, rule2->qual))				return false;			if (!equal(rule1->actions, rule2->actions))				return false;		}	}	else if (rlock2 != NULL)		return false;	return true;}/* ---------------------------------- *		RelationBuildDesc * *		Build a relation descriptor --- either a new one, or by *		recycling the given old relation object.  The latter case *		supports rebuilding a relcache entry without invalidating *		pointers to it. * -------------------------------- */static RelationRelationBuildDesc(Oid targetRelId, Relation oldrelation){	Relation	relation;	Oid			relid;	HeapTuple	pg_class_tuple;	Form_pg_class relp;	MemoryContext oldcxt;	/*	 * find the tuple in pg_class corresponding to the given relation id	 */	pg_class_tuple = ScanPgRelation(targetRelId, true);	/*	 * if no such tuple exists, return NULL	 */	if (!HeapTupleIsValid(pg_class_tuple))		return NULL;	/*	 * get information from the pg_class_tuple	 */	relid = HeapTupleGetOid(pg_class_tuple);	relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);	/*	 * allocate storage for the relation descriptor, and copy pg_class_tuple	 * to relation->rd_rel.	 */	relation = AllocateRelationDesc(oldrelation, relp);	/*	 * now we can free the memory allocated for pg_class_tuple	 */	heap_freetuple(pg_class_tuple);	/*	 * initialize the relation's relation id (relation->rd_id)	 */	RelationGetRelid(relation) = relid;	/*	 * normal relations are not nailed into the cache; nor can a pre-existing	 * relation be new.  It could be temp though.  (Actually, it could be new	 * too, but it's okay to forget that fact if forced to flush the entry.)	 */	relation->rd_refcnt = 0;	relation->rd_isnailed = false;	relation->rd_createSubid = InvalidSubTransactionId;	relation->rd_istemp = isTempNamespace(relation->rd_rel->relnamespace);	/*	 * initialize the tuple descriptor (relation->rd_att).	 */	RelationBuildTupleDesc(relation);	/*	 * Fetch rules and triggers that affect this relation	 */	if (relation->rd_rel->relhasrules)		RelationBuildRuleLock(relation);	else	{		relation->rd_rules = NULL;		relation->rd_rulescxt = NULL;	}	if (relation->rd_rel->reltriggers > 0)		RelationBuildTriggers(relation);	else		relation->trigdesc = NULL;	/*	 * if it's an index, initialize index-related information	 */	if (OidIsValid(relation->rd_rel->relam))		RelationInitIndexAccessInfo(relation);	/*	 * initialize the relation lock manager information	 */	RelationInitLockInfo(relation);		/* see lmgr.c */	/*	 * initialize physical addressing information for the relation	 */	RelationInitPhysicalAddr(relation);	/* make sure relation is marked as having no open file yet */	relation->rd_smgr = NULL;	/*	 * Insert newly created relation into relcache hash tables.	 */	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);	RelationCacheInsert(relation);	MemoryContextSwitchTo(oldcxt);	/* It's fully valid */	relation->rd_isvalid = true;	return relation;}/* * Initialize the physical addressing info (RelFileNode) for a relcache entry */static voidRelationInitPhysicalAddr(Relation relation){	if (relation->rd_rel->reltablespace)		relation->rd_node.spcNode = relation->rd_rel->reltablespace;	else		relation->rd_node.spcNode = MyDatabaseTableSpace;	if (relation->rd_rel->relisshared)		relation->rd_node.dbNode = InvalidOid;	else		relation->rd_node.dbNode = MyDatabaseId;	relation->rd_node.relNode = relation->rd_rel->relfilenode;}/* * Initialize index-access-method support data for an index relation */voidRelationInitIndexAccessInfo(Relation relation){	HeapTuple	tuple;	Form_pg_am	aform;	Datum		indclassDatum;	bool		isnull;	MemoryContext indexcxt;	MemoryContext oldcontext;	Oid		   *operator;	RegProcedure *support;	FmgrInfo   *supportinfo;	int			natts;	uint16		amstrategies;	uint16		amsupport;	/*	 * Make a copy of the pg_index entry for the index.  Since pg_index	 * contains variable-length and possibly-null fields, we have to do this	 * honestly rather than just treating it as a Form_pg_index struct.	 */	tuple = SearchSysCache(INDEXRELID,						   ObjectIdGetDatum(RelationGetRelid(relation)),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "cache lookup failed for index %u",			 RelationGetRelid(relation));	oldcontext = MemoryContextSwitchTo(CacheMemoryContext);	relation->rd_indextuple = heap_copytuple(tuple);	relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);	MemoryContextSwitchTo(oldcontext);	ReleaseSysCache(tuple);	/*	 * indclass cannot be referenced directly through the C struct, because it	 * is after the variable-width indkey field.  Therefore we extract the	 * datum the hard way and provide a direct link in the relcache.	 */	indclassDatum = fastgetattr(relation->rd_indextuple,								Anum_pg_index_indclass,								GetPgIndexDescriptor(),								&isnull);	Assert(!isnull);	relation->rd_indclass = (oidvector *) DatumGetPointer(indclassDatum);	/*	 * Make a copy of the pg_am entry for the index's access method	 */	tuple = SearchSysCache(AMOID,						   ObjectIdGetDatum(relation->rd_rel->relam),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "cache lookup failed for access method %u",			 relation->rd_rel->relam);	aform = (Form_pg_am) MemoryContextAlloc(CacheMemoryContext, sizeof *aform);	memcpy(aform, GETSTRUCT(tuple), sizeof *aform);	ReleaseSysCache(tuple);	relation->rd_am = aform;	natts = relation->rd_rel->relnatts;	if (natts != relation->rd_index->indnatts)		elog(ERROR, "relnatts disagrees with indnatts for index %u",			 RelationGetRelid(relation));	amstrategies = aform->amstrategies;	amsupport = aform->amsupport;	/*	 * Make the private context to hold index access info.	The reason we need	 * a context, and not just a couple of pallocs, is so that we won't leak	 * any subsidiary info attached to fmgr lookup records.	 *	 * Context parameters are set on the assumption that it'll probably not	 * contain much data.	 */	indexcxt = AllocSetContextCreate(CacheMemoryContext,									 RelationGetRelationName(relation),									 ALLOCSET_SMALL_MINSIZE,									 ALLOCSET_SMALL_INITSIZE,									 ALLOCSET_SMALL_MAXSIZE);	relation->rd_indexcxt = indexcxt;	/*	 * Allocate arrays to hold data	 */	relation->rd_aminfo = (RelationAmInfo *)

⌨️ 快捷键说明

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