gistutil.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 680 行 · 第 1/2 页

C
680
字号
						 oldentries + i, oldisnull[i],						 addentries + i, addisnull[i],						 attrS + i, isnullS + i);		if (neednew)			/* we already need new key, so we can skip check */			continue;		if (isnullS[i])			/* union of key may be NULL if and only if both keys are NULL */			continue;		if (!addisnull[i])		{			if (oldisnull[i] || gistKeyIsEQ(giststate, i, oldentries[i].key, attrS[i]) == false)				neednew = true;		}	}	if (neednew)	{		/* need to update key */		newtup = gistFormTuple(giststate, r, attrS, isnullS, false);		newtup->t_tid = oldtup->t_tid;	}	return newtup;}/* * find entry with lowest penalty */OffsetNumbergistchoose(Relation r, Page p, IndexTuple it,	/* it has compressed entry */		   GISTSTATE *giststate){	OffsetNumber maxoff;	OffsetNumber i;	OffsetNumber which;	float		sum_grow,				which_grow[INDEX_MAX_KEYS];	GISTENTRY	entry,				identry[INDEX_MAX_KEYS];	bool		isnull[INDEX_MAX_KEYS];	maxoff = PageGetMaxOffsetNumber(p);	*which_grow = -1.0;	which = InvalidOffsetNumber;	sum_grow = 1;	gistDeCompressAtt(giststate, r,					  it, NULL, (OffsetNumber) 0,					  identry, isnull);	Assert(maxoff >= FirstOffsetNumber);	Assert(!GistPageIsLeaf(p));	for (i = FirstOffsetNumber; i <= maxoff && sum_grow; i = OffsetNumberNext(i))	{		int			j;		IndexTuple	itup = (IndexTuple) PageGetItem(p, PageGetItemId(p, i));		if (!GistPageIsLeaf(p) && GistTupleIsInvalid(itup))		{			ereport(LOG,					(errmsg("index \"%s\" needs VACUUM or REINDEX to finish crash recovery",							RelationGetRelationName(r))));			continue;		}		sum_grow = 0;		for (j = 0; j < r->rd_att->natts; j++)		{			Datum		datum;			float		usize;			bool		IsNull;			datum = index_getattr(itup, j + 1, giststate->tupdesc, &IsNull);			gistdentryinit(giststate, j, &entry, datum, r, p, i,						   FALSE, IsNull);			usize = gistpenalty(giststate, j, &entry, IsNull,								&identry[j], isnull[j]);			if (which_grow[j] < 0 || usize < which_grow[j])			{				which = i;				which_grow[j] = usize;				if (j < r->rd_att->natts - 1 && i == FirstOffsetNumber)					which_grow[j + 1] = -1;				sum_grow += which_grow[j];			}			else if (which_grow[j] == usize)				sum_grow += usize;			else			{				sum_grow = 1;				break;			}		}	}	if (which == InvalidOffsetNumber)		which = FirstOffsetNumber;	return which;}/* * initialize a GiST entry with a decompressed version of key */voidgistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,			   Datum k, Relation r, Page pg, OffsetNumber o,			   bool l, bool isNull){	if (!isNull)	{		GISTENTRY  *dep;		gistentryinit(*e, k, r, pg, o, l);		dep = (GISTENTRY *)			DatumGetPointer(FunctionCall1(&giststate->decompressFn[nkey],										  PointerGetDatum(e)));		/* decompressFn may just return the given pointer */		if (dep != e)			gistentryinit(*e, dep->key, dep->rel, dep->page, dep->offset,						  dep->leafkey);	}	else		gistentryinit(*e, (Datum) 0, r, pg, o, l);}/* * initialize a GiST entry with a compressed version of key */voidgistcentryinit(GISTSTATE *giststate, int nkey,			   GISTENTRY *e, Datum k, Relation r,			   Page pg, OffsetNumber o, bool l, bool isNull){	if (!isNull)	{		GISTENTRY  *cep;		gistentryinit(*e, k, r, pg, o, l);		cep = (GISTENTRY *)			DatumGetPointer(FunctionCall1(&giststate->compressFn[nkey],										  PointerGetDatum(e)));		/* compressFn may just return the given pointer */		if (cep != e)			gistentryinit(*e, cep->key, cep->rel, cep->page, cep->offset,						  cep->leafkey);	}	else		gistentryinit(*e, (Datum) 0, r, pg, o, l);}IndexTuplegistFormTuple(GISTSTATE *giststate, Relation r,			  Datum attdata[], bool isnull[], bool newValues){	GISTENTRY	centry[INDEX_MAX_KEYS];	Datum		compatt[INDEX_MAX_KEYS];	int			i;	IndexTuple	res;	for (i = 0; i < r->rd_att->natts; i++)	{		if (isnull[i])			compatt[i] = (Datum) 0;		else		{			gistcentryinit(giststate, i, &centry[i], attdata[i],						   r, NULL, (OffsetNumber) 0,						   newValues,						   FALSE);			compatt[i] = centry[i].key;		}	}	res = index_form_tuple(giststate->tupdesc, compatt, isnull);	GistTupleSetValid(res);	return res;}floatgistpenalty(GISTSTATE *giststate, int attno,			GISTENTRY *orig, bool isNullOrig,			GISTENTRY *add, bool isNullAdd){	float		penalty = 0.0;	if (giststate->penaltyFn[attno].fn_strict == FALSE || (isNullOrig == FALSE && isNullAdd == FALSE))		FunctionCall3(&giststate->penaltyFn[attno],					  PointerGetDatum(orig),					  PointerGetDatum(add),					  PointerGetDatum(&penalty));	else if (isNullOrig && isNullAdd)		penalty = 0.0;	else		penalty = 1e10;			/* try to prevent to mix null and non-null								 * value */	return penalty;}/* * Initialize a new index page */voidGISTInitBuffer(Buffer b, uint32 f){	GISTPageOpaque opaque;	Page		page;	Size		pageSize;	pageSize = BufferGetPageSize(b);	page = BufferGetPage(b);	PageInit(page, pageSize, sizeof(GISTPageOpaqueData));	opaque = GistPageGetOpaque(page);	/* page was already zeroed by PageInit, so this is not needed: */	/* memset(&(opaque->nsn), 0, sizeof(GistNSN)); */	opaque->rightlink = InvalidBlockNumber;	opaque->flags = f;	opaque->gist_page_id = GIST_PAGE_ID;}/* * Verify that a freshly-read page looks sane. */voidgistcheckpage(Relation rel, Buffer buf){	Page		page = BufferGetPage(buf);	/*	 * ReadBuffer verifies that every newly-read page passes	 * PageHeaderIsValid, which means it either contains a reasonably sane	 * page header or is all-zero.	We have to defend against the all-zero	 * case, however.	 */	if (PageIsNew(page))		ereport(ERROR,				(errcode(ERRCODE_INDEX_CORRUPTED),			 errmsg("index \"%s\" contains unexpected zero page at block %u",					RelationGetRelationName(rel),					BufferGetBlockNumber(buf)),				 errhint("Please REINDEX it.")));	/*	 * Additionally check that the special area looks sane.	 */	if (((PageHeader) (page))->pd_special !=		(BLCKSZ - MAXALIGN(sizeof(GISTPageOpaqueData))))		ereport(ERROR,				(errcode(ERRCODE_INDEX_CORRUPTED),				 errmsg("index \"%s\" contains corrupted page at block %u",						RelationGetRelationName(rel),						BufferGetBlockNumber(buf)),				 errhint("Please REINDEX it.")));}/* * Allocate a new page (either by recycling, or by extending the index file) * * The returned buffer is already pinned and exclusive-locked * * Caller is responsible for initializing the page by calling GISTInitBuffer */BuffergistNewBuffer(Relation r){	Buffer		buffer;	bool		needLock;	/* First, try to get a page from FSM */	for (;;)	{		BlockNumber blkno = GetFreeIndexPage(&r->rd_node);		if (blkno == InvalidBlockNumber)			break;				/* nothing left in FSM */		buffer = ReadBuffer(r, blkno);		/*		 * We have to guard against the possibility that someone else already		 * recycled this page; the buffer may be locked if so.		 */		if (ConditionalLockBuffer(buffer))		{			Page		page = BufferGetPage(buffer);			if (PageIsNew(page))				return buffer;	/* OK to use, if never initialized */			gistcheckpage(r, buffer);			if (GistPageIsDeleted(page))				return buffer;	/* OK to use */			LockBuffer(buffer, GIST_UNLOCK);		}		/* Can't use it, so release buffer and try again */		ReleaseBuffer(buffer);	}	/* Must extend the file */	needLock = !RELATION_IS_LOCAL(r);	if (needLock)		LockRelationForExtension(r, ExclusiveLock);	buffer = ReadBuffer(r, P_NEW);	LockBuffer(buffer, GIST_EXCLUSIVE);	if (needLock)		UnlockRelationForExtension(r, ExclusiveLock);	return buffer;}Datumgistoptions(PG_FUNCTION_ARGS){	Datum		reloptions = PG_GETARG_DATUM(0);	bool		validate = PG_GETARG_BOOL(1);	bytea	   *result;	result = default_reloptions(reloptions, validate,								GIST_MIN_FILLFACTOR,								GIST_DEFAULT_FILLFACTOR);	if (result)		PG_RETURN_BYTEA_P(result);	PG_RETURN_NULL();}

⌨️ 快捷键说明

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