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

📄 index.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	Assert(PointerIsValid(indexRelation->rd_am));	procedure = indexRelation->rd_am->ambuild;	Assert(RegProcedureIsValid(procedure));	/*	 * Call the access method's build procedure	 */	OidFunctionCall3(procedure,					 PointerGetDatum(heapRelation),					 PointerGetDatum(indexRelation),					 PointerGetDatum(indexInfo));}/* * IndexBuildHeapScan - scan the heap relation to find tuples to be indexed * * This is called back from an access-method-specific index build procedure * after the AM has done whatever setup it needs.  The parent heap relation * is scanned to find tuples that should be entered into the index.  Each * such tuple is passed to the AM's callback routine, which does the right * things to add it to the new index.  After we return, the AM's index * build procedure does whatever cleanup is needed; in particular, it should * close the heap and index relations. * * The total count of heap tuples is returned.	This is for updating pg_class * statistics.	(It's annoying not to be able to do that here, but we can't * do it until after the relation is closed.)  Note that the index AM itself * must keep track of the number of index tuples; we don't do so here because * the AM might reject some of the tuples for its own reasons, such as being * unable to store NULLs. */doubleIndexBuildHeapScan(Relation heapRelation,				   Relation indexRelation,				   IndexInfo *indexInfo,				   IndexBuildCallback callback,				   void *callback_state){	HeapScanDesc scan;	HeapTuple	heapTuple;	Datum		values[INDEX_MAX_KEYS];	bool		isnull[INDEX_MAX_KEYS];	double		reltuples;	List	   *predicate;	TupleTableSlot *slot;	EState	   *estate;	ExprContext *econtext;	Snapshot	snapshot;	TransactionId OldestXmin;	/*	 * sanity checks	 */	Assert(OidIsValid(indexRelation->rd_rel->relam));	/*	 * Need an EState for evaluation of index expressions and partial-index	 * predicates.	Also a slot to hold the current tuple.	 */	estate = CreateExecutorState();	econtext = GetPerTupleExprContext(estate);	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));	/* Arrange for econtext's scan tuple to be the tuple under test */	econtext->ecxt_scantuple = slot;	/* Set up execution state for predicate, if any. */	predicate = (List *)		ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,						estate);	/*	 * Ok, begin our scan of the base relation.  We use SnapshotAny because we	 * must retrieve all tuples and do our own time qual checks.	 */	if (IsBootstrapProcessingMode())	{		snapshot = SnapshotNow;		OldestXmin = InvalidTransactionId;	}	else	{		snapshot = SnapshotAny;		OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared);	}	scan = heap_beginscan(heapRelation, /* relation */						  snapshot,		/* seeself */						  0,	/* number of keys */						  NULL);	/* scan key */	reltuples = 0;	/*	 * Scan all tuples in the base relation.	 */	while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)	{		bool		tupleIsAlive;		CHECK_FOR_INTERRUPTS();		if (snapshot == SnapshotAny)		{			/* do our own time qual check */			bool		indexIt;			/*			 * We could possibly get away with not locking the buffer here,			 * since caller should hold ShareLock on the relation, but let's			 * be conservative about it.			 */			LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);			switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin,											 scan->rs_cbuf))			{				case HEAPTUPLE_DEAD:					indexIt = false;					tupleIsAlive = false;					break;				case HEAPTUPLE_LIVE:					indexIt = true;					tupleIsAlive = true;					break;				case HEAPTUPLE_RECENTLY_DEAD:					/*					 * If tuple is recently deleted then we must index it					 * anyway to preserve MVCC semantics.  (Pre-existing					 * transactions could try to use the index after we					 * finish building it, and may need to see such tuples.)					 */					indexIt = true;					tupleIsAlive = false;					break;				case HEAPTUPLE_INSERT_IN_PROGRESS:					/*					 * Since caller should hold ShareLock or better, we should					 * not see any tuples inserted by open transactions ---					 * unless it's our own transaction. (Consider INSERT					 * followed by CREATE INDEX within a transaction.)	An					 * exception occurs when reindexing a system catalog,					 * because we often release lock on system catalogs before					 * committing.					 */					if (!TransactionIdIsCurrentTransactionId(								   HeapTupleHeaderGetXmin(heapTuple->t_data))						&& !IsSystemRelation(heapRelation))						elog(ERROR, "concurrent insert in progress");					indexIt = true;					tupleIsAlive = true;					break;				case HEAPTUPLE_DELETE_IN_PROGRESS:					/*					 * Since caller should hold ShareLock or better, we should					 * not see any tuples deleted by open transactions ---					 * unless it's our own transaction. (Consider DELETE					 * followed by CREATE INDEX within a transaction.)	An					 * exception occurs when reindexing a system catalog,					 * because we often release lock on system catalogs before					 * committing.					 */					Assert(!(heapTuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));					if (!TransactionIdIsCurrentTransactionId(								   HeapTupleHeaderGetXmax(heapTuple->t_data))						&& !IsSystemRelation(heapRelation))						elog(ERROR, "concurrent delete in progress");					indexIt = true;					tupleIsAlive = false;					break;				default:					elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");					indexIt = tupleIsAlive = false;		/* keep compiler quiet */					break;			}			LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);			if (!indexIt)				continue;		}		else		{			/* heap_getnext did the time qual check */			tupleIsAlive = true;		}		reltuples += 1;		MemoryContextReset(econtext->ecxt_per_tuple_memory);		/* Set up for predicate or expression evaluation */		ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);		/*		 * In a partial index, discard tuples that don't satisfy the		 * predicate.		 */		if (predicate != NIL)		{			if (!ExecQual(predicate, econtext, false))				continue;		}		/*		 * For the current heap tuple, extract all the attributes we use in		 * this index, and note which are null.  This also performs evaluation		 * of any expressions needed.		 */		FormIndexDatum(indexInfo,					   slot,					   estate,					   values,					   isnull);		/*		 * You'd think we should go ahead and build the index tuple here, but		 * some index AMs want to do further processing on the data first.	So		 * pass the values[] and isnull[] arrays, instead.		 */		/* Call the AM's callback routine to process the tuple */		callback(indexRelation, heapTuple, values, isnull, tupleIsAlive,				 callback_state);	}	heap_endscan(scan);	ExecDropSingleTupleTableSlot(slot);	FreeExecutorState(estate);	/* These may have been pointing to the now-gone estate */	indexInfo->ii_ExpressionsState = NIL;	indexInfo->ii_PredicateState = NIL;	return reltuples;}/* * IndexGetRelation: given an index's relation OID, get the OID of the * relation it is an index on.	Uses the system cache. */static OidIndexGetRelation(Oid indexId){	HeapTuple	tuple;	Form_pg_index index;	Oid			result;	tuple = SearchSysCache(INDEXRELID,						   ObjectIdGetDatum(indexId),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "cache lookup failed for index %u", indexId);	index = (Form_pg_index) GETSTRUCT(tuple);	Assert(index->indexrelid == indexId);	result = index->indrelid;	ReleaseSysCache(tuple);	return result;}/* * reindex_index - This routine is used to recreate a single index */voidreindex_index(Oid indexId){	Relation	iRel,				heapRelation;	Oid			heapId;	bool		inplace;	/*	 * Open and lock the parent heap relation.	ShareLock is sufficient since	 * we only need to be sure no schema or data changes are going on.	 */	heapId = IndexGetRelation(indexId);	heapRelation = heap_open(heapId, ShareLock);	/*	 * Open the target index relation and get an exclusive lock on it, to	 * ensure that no one else is touching this particular index.	 */	iRel = index_open(indexId);	LockRelation(iRel, AccessExclusiveLock);	/*	 * If it's a shared index, we must do inplace processing (because we have	 * no way to update relfilenode in other databases).  Otherwise we can do	 * it the normal transaction-safe way.	 *	 * Since inplace processing isn't crash-safe, we only allow it in a	 * standalone backend.	(In the REINDEX TABLE and REINDEX DATABASE cases,	 * the caller should have detected this.)	 */	inplace = iRel->rd_rel->relisshared;	if (inplace && IsUnderPostmaster)		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("shared index \"%s\" can only be reindexed in stand-alone mode",						RelationGetRelationName(iRel))));	PG_TRY();	{		IndexInfo  *indexInfo;		/* Suppress use of the target index while rebuilding it */		SetReindexProcessing(heapId, indexId);		/* Fetch info needed for index_build */		indexInfo = BuildIndexInfo(iRel);		if (inplace)		{			/* Truncate the actual file (and discard buffers) */			RelationTruncate(iRel, 0);		}		else		{			/*			 * We'll build a new physical relation for the index.			 */			setNewRelfilenode(iRel);		}		/* Initialize the index and rebuild */		index_build(heapRelation, iRel, indexInfo);		/*		 * index_build will close both the heap and index relations (but not		 * give up the locks we hold on them).	So we're done.		 */	}	PG_CATCH();	{		/* Make sure flag gets cleared on error exit */		ResetReindexProcessing();		PG_RE_THROW();	}	PG_END_TRY();	ResetReindexProcessing();}/* * reindex_relation - This routine is used to recreate all indexes * of a relation (and optionally its toast relation too, if any). * * Returns true if any indexes were rebuilt.  Note that a * CommandCounterIncrement will occur after each index rebuild. */boolreindex_relation(Oid relid, bool toast_too){	Relation	rel;	Oid			toast_relid;	bool		is_pg_class;	bool		result;	List	   *indexIds,			   *doneIndexes;	ListCell   *indexId;	/*	 * Open and lock the relation.	ShareLock is sufficient since we only need	 * to prevent schema and data changes in it.	 */	rel = heap_open(relid, ShareLock);	toast_relid = rel->rd_rel->reltoastrelid;	/*	 * Get the list of index OIDs for this relation.  (We trust to the	 * relcache to get this with a sequential scan if ignoring system	 * indexes.)	 */	indexIds = RelationGetIndexList(rel);	/*	 * reindex_index will attempt to update the pg_class rows for the relation	 * and index.  If we are processing pg_class itself, we want to make sure	 * that the updates do not try to insert index entries into indexes we	 * have not processed yet.	(When we are trying to recover from corrupted	 * indexes, that could easily cause a crash.) We can accomplish this	 * because CatalogUpdateIndexes will use the relcache's index list to know	 * which indexes to update. We just force the index list to be only the	 * stuff we've processed.	 *	 * It is okay to not insert entries into the indexes we have not processed	 * yet because all of this is transaction-safe.  If we fail partway	 * through, the updated rows are dead and it doesn't matter whether they	 * have index entries.	Also, a new pg_class index will be created with an	 * entry for its own pg_class row because we do setNewRelfilenode() before	 * we do index_build().	 *	 * Note that we also clear pg_class's rd_oidindex until the loop is done,	 * so that that index can't be accessed either.  This means we cannot	 * safely generate new relation OIDs while in the loop; shouldn't be a	 * problem.	 */	is_pg_class = (RelationGetRelid(rel) == RelationRelationId);	doneIndexes = NIL;	/* Reindex all the indexes. */	foreach(indexId, indexIds)	{		Oid			indexOid = lfirst_oid(indexId);		if (is_pg_class)			RelationSetIndexList(rel, doneIndexes, InvalidOid);		reindex_index(indexOid);		CommandCounterIncrement();		if (is_pg_class)			doneIndexes = lappend_oid(doneIndexes, indexOid);	}	if (is_pg_class)		RelationSetIndexList(rel, indexIds, ClassOidIndexId);	/*	 * Close rel, but continue to hold the lock.	 */	heap_close(rel, NoLock);	result = (indexIds != NIL);	/*	 * If the relation has a secondary toast rel, reindex that too while we	 * still hold the lock on the master table.	 */	if (toast_too && OidIsValid(toast_relid))		result |= reindex_relation(toast_relid, false);	return result;}

⌨️ 快捷键说明

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