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

📄 index.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
 */Oidindex_create(Oid heapRelationId,			 const char *indexRelationName,			 Oid indexRelationId,			 IndexInfo *indexInfo,			 Oid accessMethodObjectId,			 Oid tableSpaceId,			 Oid *classObjectId,			 bool primary,			 bool isconstraint,			 bool allow_system_table_mods,			 bool skip_build){	Relation	pg_class;	Relation	heapRelation;	Relation	indexRelation;	TupleDesc	indexTupDesc;	bool		shared_relation;	Oid			namespaceId;	int			i;	pg_class = heap_open(RelationRelationId, RowExclusiveLock);	/*	 * Only SELECT ... FOR UPDATE/SHARE are allowed while doing this	 */	heapRelation = heap_open(heapRelationId, ShareLock);	/*	 * The index will be in the same namespace as its parent table, and is	 * shared across databases if and only if the parent is.	 */	namespaceId = RelationGetNamespace(heapRelation);	shared_relation = heapRelation->rd_rel->relisshared;	/*	 * check parameters	 */	if (indexInfo->ii_NumIndexAttrs < 1)		elog(ERROR, "must index at least one column");	if (!allow_system_table_mods &&		IsSystemRelation(heapRelation) &&		IsNormalProcessingMode())		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("user-defined indexes on system catalog tables are not supported")));	/*	 * We cannot allow indexing a shared relation after initdb (because	 * there's no way to make the entry in other databases' pg_class).	 * Unfortunately we can't distinguish initdb from a manually started	 * standalone backend (toasting of shared rels happens after the bootstrap	 * phase, so checking IsBootstrapProcessingMode() won't work).  However,	 * we can at least prevent this mistake under normal multi-user operation.	 */	if (shared_relation && IsUnderPostmaster)		ereport(ERROR,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("shared indexes cannot be created after initdb")));	if (get_relname_relid(indexRelationName, namespaceId))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_TABLE),				 errmsg("relation \"%s\" already exists",						indexRelationName)));	/*	 * construct tuple descriptor for index tuples	 */	indexTupDesc = ConstructTupleDescriptor(heapRelation,											indexInfo,											classObjectId);	/*	 * Allocate an OID for the index, unless we were told what to use.	 *	 * The OID will be the relfilenode as well, so make sure it doesn't	 * collide with either pg_class OIDs or existing physical files.	 */	if (!OidIsValid(indexRelationId))		indexRelationId = GetNewRelFileNode(tableSpaceId, shared_relation,											pg_class);	/*	 * create the index relation's relcache entry and physical disk file. (If	 * we fail further down, it's the smgr's responsibility to remove the disk	 * file again.)	 */	indexRelation = heap_create(indexRelationName,								namespaceId,								tableSpaceId,								indexRelationId,								indexTupDesc,								RELKIND_INDEX,								shared_relation,								allow_system_table_mods);	Assert(indexRelationId == RelationGetRelid(indexRelation));	/*	 * Obtain exclusive lock on it.  Although no other backends can see it	 * until we commit, this prevents deadlock-risk complaints from lock	 * manager in cases such as CLUSTER.	 */	LockRelation(indexRelation, AccessExclusiveLock);	/*	 * Fill in fields of the index's pg_class entry that are not set correctly	 * by heap_create.	 *	 * XXX should have a cleaner way to create cataloged indexes	 */	indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;	indexRelation->rd_rel->relam = accessMethodObjectId;	indexRelation->rd_rel->relkind = RELKIND_INDEX;	indexRelation->rd_rel->relhasoids = false;	/*	 * store index's pg_class entry	 */	UpdateRelationRelation(pg_class, indexRelation);	/* done with pg_class */	heap_close(pg_class, RowExclusiveLock);	/*	 * now update the object id's of all the attribute tuple forms in the	 * index relation's tuple descriptor	 */	InitializeAttributeOids(indexRelation,							indexInfo->ii_NumIndexAttrs,							indexRelationId);	/*	 * append ATTRIBUTE tuples for the index	 */	AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs);	/* ----------------	 *	  update pg_index	 *	  (append INDEX tuple)	 *	 *	  Note that this stows away a representation of "predicate".	 *	  (Or, could define a rule to maintain the predicate) --Nels, Feb '92	 * ----------------	 */	UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo,						classObjectId, primary);	/*	 * Register constraint and dependencies for the index.	 *	 * If the index is from a CONSTRAINT clause, construct a pg_constraint	 * entry. The index is then linked to the constraint, which in turn is	 * linked to the table.  If it's not a CONSTRAINT, make the dependency	 * directly on the table.	 *	 * We don't need a dependency on the namespace, because there'll be an	 * indirect dependency via our parent table.	 *	 * During bootstrap we can't register any dependencies, and we don't try	 * to make a constraint either.	 */	if (!IsBootstrapProcessingMode())	{		ObjectAddress myself,					referenced;		myself.classId = RelationRelationId;		myself.objectId = indexRelationId;		myself.objectSubId = 0;		if (isconstraint)		{			char		constraintType;			Oid			conOid;			if (primary)				constraintType = CONSTRAINT_PRIMARY;			else if (indexInfo->ii_Unique)				constraintType = CONSTRAINT_UNIQUE;			else			{				elog(ERROR, "constraint must be PRIMARY or UNIQUE");				constraintType = 0;		/* keep compiler quiet */			}			/* Shouldn't have any expressions */			if (indexInfo->ii_Expressions)				elog(ERROR, "constraints can't have index expressions");			conOid = CreateConstraintEntry(indexRelationName,										   namespaceId,										   constraintType,										   false,		/* isDeferrable */										   false,		/* isDeferred */										   heapRelationId,										   indexInfo->ii_KeyAttrNumbers,										   indexInfo->ii_NumIndexAttrs,										   InvalidOid,	/* no domain */										   InvalidOid,	/* no foreign key */										   NULL,										   0,										   ' ',										   ' ',										   ' ',										   InvalidOid,	/* no associated index */										   NULL,		/* no check constraint */										   NULL,										   NULL);			referenced.classId = ConstraintRelationId;			referenced.objectId = conOid;			referenced.objectSubId = 0;			recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);		}		else		{			/* Create auto dependencies on simply-referenced columns */			for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)			{				if (indexInfo->ii_KeyAttrNumbers[i] != 0)				{					referenced.classId = RelationRelationId;					referenced.objectId = heapRelationId;					referenced.objectSubId = indexInfo->ii_KeyAttrNumbers[i];					recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);				}			}		}		/* Store dependency on operator classes */		for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)		{			referenced.classId = OperatorClassRelationId;			referenced.objectId = classObjectId[i];			referenced.objectSubId = 0;			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);		}		/* Store dependencies on anything mentioned in index expressions */		if (indexInfo->ii_Expressions)		{			recordDependencyOnSingleRelExpr(&myself,										  (Node *) indexInfo->ii_Expressions,											heapRelationId,											DEPENDENCY_NORMAL,											DEPENDENCY_AUTO);		}		/* Store dependencies on anything mentioned in predicate */		if (indexInfo->ii_Predicate)		{			recordDependencyOnSingleRelExpr(&myself,											(Node *) indexInfo->ii_Predicate,											heapRelationId,											DEPENDENCY_NORMAL,											DEPENDENCY_AUTO);		}	}	/*	 * Advance the command counter so that we can see the newly-entered	 * catalog tuples for the index.	 */	CommandCounterIncrement();	/*	 * In bootstrap mode, we have to fill in the index strategy structure with	 * information from the catalogs.  If we aren't bootstrapping, then the	 * relcache entry has already been rebuilt thanks to sinval update during	 * CommandCounterIncrement.	 */	if (IsBootstrapProcessingMode())		RelationInitIndexAccessInfo(indexRelation);	else		Assert(indexRelation->rd_indexcxt != NULL);	/*	 * If this is bootstrap (initdb) time, then we don't actually fill in the	 * index yet.  We'll be creating more indexes and classes later, so we	 * delay filling them in until just before we're done with bootstrapping.	 * Similarly, if the caller specified skip_build then filling the index is	 * delayed till later (ALTER TABLE can save work in some cases with this).	 * Otherwise, we call the AM routine that constructs the index.	 *	 * In normal processing mode, the heap and index relations are closed, but	 * we continue to hold the ShareLock on the heap and the exclusive lock on	 * the index that we acquired above, until end of transaction.	 */	if (IsBootstrapProcessingMode())	{		index_register(heapRelationId, indexRelationId, indexInfo);		/* XXX shouldn't we close the heap and index rels here? */	}	else if (skip_build)	{		/* caller is responsible for filling the index later on */		relation_close(indexRelation, NoLock);		heap_close(heapRelation, NoLock);	}	else	{		index_build(heapRelation, indexRelation, indexInfo);		/* index_build closes the passed rels */	}	return indexRelationId;}/* *		index_drop * * NOTE: this routine should now only be called through performDeletion(), * else associated dependencies won't be cleaned up. */voidindex_drop(Oid indexId){	Oid			heapId;	Relation	userHeapRelation;	Relation	userIndexRelation;	Relation	indexRelation;	HeapTuple	tuple;	bool		hasexprs;	/*	 * To drop an index safely, we must grab exclusive lock on its parent	 * table; otherwise there could be other backends using the index!	 * Exclusive lock on the index alone is insufficient because another	 * backend might be in the midst of devising a query plan that will use	 * the index.  The parser and planner take care to hold an appropriate	 * lock on the parent table while working, but having them hold locks on	 * all the indexes too seems overly expensive.	We do grab exclusive lock	 * on the index too, just to be safe. Both locks must be held till end of	 * transaction, else other backends will still see this index in pg_index.	 */	heapId = IndexGetRelation(indexId);	userHeapRelation = heap_open(heapId, AccessExclusiveLock);	userIndexRelation = index_open(indexId);	LockRelation(userIndexRelation, AccessExclusiveLock);	/*	 * Schedule physical removal of the file	 */	RelationOpenSmgr(userIndexRelation);	smgrscheduleunlink(userIndexRelation->rd_smgr,					   userIndexRelation->rd_istemp);	/*	 * Close and flush the index's relcache entry, to ensure relcache doesn't	 * try to rebuild it while we're deleting catalog entries. We keep the	 * lock though.	 */	index_close(userIndexRelation);	RelationForgetRelation(indexId);	/*	 * fix INDEX relation, and check for expressional index	 */	indexRelation = heap_open(IndexRelationId, RowExclusiveLock);	tuple = SearchSysCache(INDEXRELID,						   ObjectIdGetDatum(indexId),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "cache lookup failed for index %u", indexId);	hasexprs = !heap_attisnull(tuple, Anum_pg_index_indexprs);	simple_heap_delete(indexRelation, &tuple->t_self);	ReleaseSysCache(tuple);	heap_close(indexRelation, RowExclusiveLock);	/*	 * if it has any expression columns, we might have stored statistics about	 * them.	 */	if (hasexprs)		RemoveStatistics(indexId, 0);	/*	 * fix ATTRIBUTE relation	 */	DeleteAttributeTuples(indexId);	/*	 * fix RELATION relation	 */	DeleteRelationTuple(indexId);	/*	 * We are presently too lazy to attempt to compute the new correct value	 * of relhasindex (the next VACUUM will fix it if necessary). So there is	 * no need to update the pg_class tuple for the owning relation. But we	 * must send out a shared-cache-inval notice on the owning relation to	 * ensure other backends update their relcache lists of indexes.	 */	CacheInvalidateRelcache(userHeapRelation);	/*	 * Close owning rel, but keep lock	 */	heap_close(userHeapRelation, NoLock);}/* ---------------------------------------------------------------- *						index_build support * ---------------------------------------------------------------- *//* ---------------- *		BuildIndexInfo *			Construct an IndexInfo record for an open index * * IndexInfo stores the information about the index that's needed by * FormIndexDatum, which is used for both index_build() and later insertion * of individual index tuples.	Normally we build an IndexInfo for an index * just once per command, and then use it for (potentially) many tuples. * ---------------- */IndexInfo *BuildIndexInfo(Relation index){	IndexInfo  *ii = makeNode(IndexInfo);	Form_pg_index indexStruct = index->rd_index;	int			i;	int			numKeys;	/* check the number of keys, and copy attr numbers into the IndexInfo */	numKeys = indexStruct->indnatts;	if (numKeys < 1 || numKeys > INDEX_MAX_KEYS)		elog(ERROR, "invalid indnatts %d for index %u",			 numKeys, RelationGetRelid(index));	ii->ii_NumIndexAttrs = numKeys;	for (i = 0; i < numKeys; i++)		ii->ii_KeyAttrNumbers[i] = indexStruct->indkey.values[i];	/* fetch any expressions needed for expressional indexes */	ii->ii_Expressions = RelationGetIndexExpressions(index);

⌨️ 快捷键说明

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