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

📄 index.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 4 页
字号:
	 *	 * If we found zero tuples in the scan, do NOT believe it; instead put	 * a bogus estimate into the statistics fields.  Otherwise, the common	 * pattern "CREATE TABLE; CREATE INDEX; insert data" leaves the table	 * with zero size statistics until a VACUUM is done.  The optimizer will	 * generate very bad plans if the stats claim the table is empty when	 * it is actually sizable.  See also CREATE TABLE in heap.c.	 * ----------------	 */	relpages = RelationGetNumberOfBlocks(whichRel);	if (reltuples == 0)	{		if (relpages == 0)		{			/* Bogus defaults for a virgin table, same as heap.c */			reltuples = 1000;			relpages = 10;		}		else if (whichRel->rd_rel->relkind == RELKIND_INDEX && relpages <= 2)		{			/* Empty index, leave bogus defaults in place */			reltuples = 1000;		}		else			reltuples = relpages * NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts);	}	/*	 * We shouldn't have to do this, but we do...  Modify the reldesc in	 * place with the new values so that the cache contains the latest	 * copy.	 */	whichRel->rd_rel->relhasindex = hasindex;	whichRel->rd_rel->relpages = relpages;	whichRel->rd_rel->reltuples = reltuples;	/* ----------------	 *	Update statistics in pg_class.	 * ----------------	 */	if (IsBootstrapProcessingMode())	{		/*		 * At bootstrap time, we don't need to worry about concurrency or		 * visibility of changes, so we cheat.		 */		rd_rel = (Form_pg_class) GETSTRUCT(tuple);		rd_rel->relpages = relpages;		rd_rel->reltuples = reltuples;		rd_rel->relhasindex = hasindex;		WriteBuffer(pg_class_scan->rs_cbuf);	}	else	{		/* During normal processing, must work harder. */		for (i = 0; i < Natts_pg_class; i++)		{			nulls[i] = heap_attisnull(tuple, i + 1) ? 'n' : ' ';			replace[i] = ' ';			values[i] = (Datum) NULL;		}		replace[Anum_pg_class_relpages - 1] = 'r';		values[Anum_pg_class_relpages - 1] = (Datum) relpages;		replace[Anum_pg_class_reltuples - 1] = 'r';		values[Anum_pg_class_reltuples - 1] = (Datum) reltuples;		replace[Anum_pg_class_relhasindex - 1] = 'r';		values[Anum_pg_class_relhasindex - 1] = CharGetDatum(hasindex);		newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace);		heap_replace(pg_class, &tuple->t_self, newtup, NULL);		CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);		CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);		CatalogCloseIndices(Num_pg_class_indices, idescs);		pfree(newtup);	}	if (!IsBootstrapProcessingMode())		pfree(tuple);	else		heap_endscan(pg_class_scan);	heap_close(pg_class);	heap_close(whichRel);}/* ------------------------- *		FillDummyExprContext *			Sets up dummy ExprContext and TupleTableSlot objects for use *			with ExecQual. * ------------------------- */voidFillDummyExprContext(ExprContext *econtext,					 TupleTableSlot *slot,					 TupleDesc tupdesc,					 Buffer buffer){	econtext->ecxt_scantuple = slot;	econtext->ecxt_innertuple = NULL;	econtext->ecxt_outertuple = NULL;	econtext->ecxt_param_list_info = NULL;	econtext->ecxt_range_table = NULL;	slot->ttc_tupleDescriptor = tupdesc;	slot->ttc_buffer = buffer;	slot->ttc_shouldFree = false;}/* ---------------- *		DefaultBuild * ---------------- */static voidDefaultBuild(Relation heapRelation,			 Relation indexRelation,			 int numberOfAttributes,			 AttrNumber *attributeNumber,			 IndexStrategy indexStrategy,		/* not used */			 uint16 parameterCount,		/* not used */			 Datum *parameter,	/* not used */			 FuncIndexInfoPtr funcInfo,			 PredInfo *predInfo){	HeapScanDesc scan;	HeapTuple	heapTuple;	IndexTuple	indexTuple;	TupleDesc	heapDescriptor;	TupleDesc	indexDescriptor;	Datum	   *datum;	char	   *nullv;	long		reltuples,				indtuples;#ifndef OMIT_PARTIAL_INDEX	ExprContext *econtext;	TupleTable	tupleTable;	TupleTableSlot *slot;#endif	Node	   *predicate;	Node	   *oldPred;	InsertIndexResult insertResult;	/* ----------------	 *	more & better checking is needed	 * ----------------	 */	Assert(OidIsValid(indexRelation->rd_rel->relam));	/* XXX */	/* ----------------	 *	get the tuple descriptors from the relations so we know	 *	how to form the index tuples..	 * ----------------	 */	heapDescriptor = RelationGetDescr(heapRelation);	indexDescriptor = RelationGetDescr(indexRelation);	/* ----------------	 *	datum and null are arrays in which we collect the index attributes	 *	when forming a new index tuple.	 * ----------------	 */	datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);	nullv = (char *) palloc(numberOfAttributes * sizeof *nullv);	/*	 * If this is a predicate (partial) index, we will need to evaluate	 * the predicate using ExecQual, which requires the current tuple to	 * be in a slot of a TupleTable.  In addition, ExecQual must have an	 * ExprContext referring to that slot.	Here, we initialize dummy	 * TupleTable and ExprContext objects for this purpose. --Nels, Feb	 * '92	 */	predicate = predInfo->pred;	oldPred = predInfo->oldPred;#ifndef OMIT_PARTIAL_INDEX	if (predicate != NULL || oldPred != NULL)	{		tupleTable = ExecCreateTupleTable(1);		slot = ExecAllocTableSlot(tupleTable);		econtext = makeNode(ExprContext);		/* last parameter was junk being sent bjm 1998/08/17 */		FillDummyExprContext(econtext, slot, heapDescriptor, InvalidBuffer);	}	else	{		econtext = NULL;		tupleTable = 0;		slot = NULL;	}#endif	 /* OMIT_PARTIAL_INDEX */	/* ----------------	 *	Ok, begin our scan of the base relation.	 * ----------------	 */	scan = heap_beginscan(heapRelation, /* relation */						  0,	/* start at end */						  SnapshotNow,	/* seeself */						  0,	/* number of keys */						  (ScanKey) NULL);		/* scan key */	reltuples = indtuples = 0;	/* ----------------	 *	for each tuple in the base relation, we create an index	 *	tuple and add it to the index relation.  We keep a running	 *	count of the number of tuples so that we can update pg_class	 *	with correct statistics when we're done building the index.	 * ----------------	 */	while (HeapTupleIsValid(heapTuple = heap_getnext(scan, 0)))	{		reltuples++;#ifndef OMIT_PARTIAL_INDEX		/*		 * If oldPred != NULL, this is an EXTEND INDEX command, so skip		 * this tuple if it was already in the existing partial index		 */		if (oldPred != NULL)		{			/* SetSlotContents(slot, heapTuple); */			slot->val = heapTuple;			if (ExecQual((List *) oldPred, econtext) == true)			{				indtuples++;				continue;			}		}		/*		 * Skip this tuple if it doesn't satisfy the partial-index		 * predicate		 */		if (predicate != NULL)		{			/* SetSlotContents(slot, heapTuple); */			slot->val = heapTuple;			if (ExecQual((List *) predicate, econtext) == false)				continue;		}#endif	 /* OMIT_PARTIAL_INDEX */		indtuples++;		/* ----------------		 *	FormIndexDatum fills in its datum and null parameters		 *	with attribute information taken from the given heap tuple.		 * ----------------		 */		FormIndexDatum(numberOfAttributes,		/* num attributes */					   attributeNumber, /* array of att nums to extract */					   heapTuple,		/* tuple from base relation */					   heapDescriptor,	/* heap tuple's descriptor */					   datum,	/* return: array of attributes */					   nullv,	/* return: array of char's */					   funcInfo);		indexTuple = index_formtuple(indexDescriptor,									 datum,									 nullv);		indexTuple->t_tid = heapTuple->t_self;		insertResult = index_insert(indexRelation, datum, nullv,									&(heapTuple->t_self), heapRelation);		if (insertResult)			pfree(insertResult);		pfree(indexTuple);	}	heap_endscan(scan);#ifndef OMIT_PARTIAL_INDEX	if (predicate != NULL || oldPred != NULL)	{		ExecDestroyTupleTable(tupleTable, false);	}#endif	 /* OMIT_PARTIAL_INDEX */	pfree(nullv);	pfree(datum);	/*	 * Okay, now update the reltuples and relpages statistics for both the	 * heap relation and the index.  These statistics are used by the	 * planner to choose a scan type.  They are maintained generally by	 * the vacuum daemon, but we update them here to make the index useful	 * as soon as possible.	 */	UpdateStats(RelationGetRelid(heapRelation), reltuples, true);	UpdateStats(RelationGetRelid(indexRelation), indtuples, false);	if (oldPred != NULL)	{		if (indtuples == reltuples)			predicate = NULL;		UpdateIndexPredicate(RelationGetRelid(indexRelation),							 oldPred, predicate);	}}/* ---------------- *		index_build * ---------------- */voidindex_build(Relation heapRelation,			Relation indexRelation,			int numberOfAttributes,			AttrNumber *attributeNumber,			uint16 parameterCount,			Datum *parameter,			FuncIndexInfo *funcInfo,			PredInfo *predInfo){	RegProcedure procedure;	/* ----------------	 *	sanity checks	 * ----------------	 */	Assert(RelationIsValid(indexRelation));	Assert(PointerIsValid(indexRelation->rd_am));	procedure = indexRelation->rd_am->ambuild;	/* ----------------	 *	use the access method build procedure if supplied..	 * ----------------	 */	if (RegProcedureIsValid(procedure))		fmgr(procedure,			 heapRelation,			 indexRelation,			 numberOfAttributes,			 attributeNumber,			 RelationGetIndexStrategy(indexRelation),			 parameterCount,			 parameter,			 funcInfo,			 predInfo);	else		DefaultBuild(heapRelation,					 indexRelation,					 numberOfAttributes,					 attributeNumber,					 RelationGetIndexStrategy(indexRelation),					 parameterCount,					 parameter,					 funcInfo,					 predInfo);}/* * IndexIsUnique: given an index's relation OID, see if it * is unique using the system cache. */boolIndexIsUnique(Oid indexId){	HeapTuple	tuple;	Form_pg_index index;	tuple = SearchSysCacheTuple(INDEXRELID,								ObjectIdGetDatum(indexId),								0, 0, 0);	if (!HeapTupleIsValid(tuple))	{		elog(ERROR, "IndexIsUnique: can't find index id %u",			 indexId);	}	index = (Form_pg_index) GETSTRUCT(tuple);	Assert(index->indexrelid == indexId);	return index->indisunique;}/* * IndexIsUniqueNoCache: same as above function, but don't use the * system cache.  if we are called from btbuild, the transaction * that is adding the entry to pg_index has not been committed yet. * the system cache functions will do a heap scan, but only with * NowTimeQual, not SelfTimeQual, so it won't find tuples added * by the current transaction (which is good, because if the transaction * is aborted, you don't want the tuples sitting around in the cache). * so anyway, we have to do our own scan with SelfTimeQual. * this is only called when a new index is created, so it's OK * if it's slow. */boolIndexIsUniqueNoCache(Oid indexId){	Relation	pg_index;	ScanKeyData skey[1];	HeapScanDesc scandesc;	HeapTuple	tuple;	Form_pg_index index;	bool		isunique;	pg_index = heap_openr(IndexRelationName);	ScanKeyEntryInitialize(&skey[0], (bits16) 0x0,						   Anum_pg_index_indexrelid,						   (RegProcedure) F_OIDEQ,						   ObjectIdGetDatum(indexId));	scandesc = heap_beginscan(pg_index, 0, SnapshotSelf, 1, skey);	/* NO CACHE */	tuple = heap_getnext(scandesc, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "IndexIsUniqueNoCache: can't find index id %u", indexId);	index = (Form_pg_index) GETSTRUCT(tuple);	Assert(index->indexrelid == indexId);	isunique = index->indisunique;	heap_endscan(scandesc);	heap_close(pg_index);	return isunique;}

⌨️ 快捷键说明

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