gistutil.c

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

C
680
字号
/*------------------------------------------------------------------------- * * gistutil.c *	  utilities routines for the postgres GiST index access method. * * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION *			$PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.25 2008/01/01 19:45:46 momjian Exp $ *------------------------------------------------------------------------- */#include "postgres.h"#include "access/gist_private.h"#include "access/heapam.h"#include "access/reloptions.h"#include "storage/freespace.h"/* * static *S used for temrorary storage (saves stack and palloc() call) */static Datum attrS[INDEX_MAX_KEYS];static bool isnullS[INDEX_MAX_KEYS];/* * Write itup vector to page, has no control of free space */OffsetNumbergistfillbuffer(Relation r, Page page, IndexTuple *itup,			   int len, OffsetNumber off){	OffsetNumber l = InvalidOffsetNumber;	int			i;	if (off == InvalidOffsetNumber)		off = (PageIsEmpty(page)) ? FirstOffsetNumber :			OffsetNumberNext(PageGetMaxOffsetNumber(page));	for (i = 0; i < len; i++)	{		l = PageAddItem(page, (Item) itup[i], IndexTupleSize(itup[i]),						off, false, false);		if (l == InvalidOffsetNumber)			elog(ERROR, "failed to add item to index page in \"%s\"",				 RelationGetRelationName(r));		off++;	}	return l;}/* * Check space for itup vector on page */boolgistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace){	unsigned int size = freespace,				deleted = 0;	int			i;	for (i = 0; i < len; i++)		size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);	if (todelete != InvalidOffsetNumber)	{		IndexTuple	itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, todelete));		deleted = IndexTupleSize(itup) + sizeof(ItemIdData);	}	return (PageGetFreeSpace(page) + deleted < size);}boolgistfitpage(IndexTuple *itvec, int len){	int			i;	Size		size = 0;	for (i = 0; i < len; i++)		size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);	/* TODO: Consider fillfactor */	return (size <= GiSTPageSize);}/* * Read buffer into itup vector */IndexTuple *gistextractpage(Page page, int *len /* out */ ){	OffsetNumber i,				maxoff;	IndexTuple *itvec;	maxoff = PageGetMaxOffsetNumber(page);	*len = maxoff;	itvec = palloc(sizeof(IndexTuple) * maxoff);	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))		itvec[i - FirstOffsetNumber] = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));	return itvec;}/* * join two vectors into one */IndexTuple *gistjoinvector(IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen){	itvec = (IndexTuple *) repalloc((void *) itvec, sizeof(IndexTuple) * ((*len) + addlen));	memmove(&itvec[*len], additvec, sizeof(IndexTuple) * addlen);	*len += addlen;	return itvec;}/* * make plain IndexTupleVector */IndexTupleData *gistfillitupvec(IndexTuple *vec, int veclen, int *memlen){	char	   *ptr,			   *ret;	int			i;	*memlen = 0;	for (i = 0; i < veclen; i++)		*memlen += IndexTupleSize(vec[i]);	ptr = ret = palloc(*memlen);	for (i = 0; i < veclen; i++)	{		memcpy(ptr, vec[i], IndexTupleSize(vec[i]));		ptr += IndexTupleSize(vec[i]);	}	return (IndexTupleData *) ret;}/* * Make unions of keys in IndexTuple vector, return FALSE if itvec contains * invalid tuple. Resulting Datums aren't compressed. */boolgistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startkey,				   Datum *attr, bool *isnull){	int			i;	GistEntryVector *evec;	int			attrsize;	evec = (GistEntryVector *) palloc((len + 2) * sizeof(GISTENTRY) + GEVHDRSZ);	for (i = startkey; i < giststate->tupdesc->natts; i++)	{		int			j;		evec->n = 0;		if (!isnull[i])		{			gistentryinit(evec->vector[evec->n], attr[i],						  NULL, NULL, (OffsetNumber) 0,						  FALSE);			evec->n++;		}		for (j = 0; j < len; j++)		{			Datum		datum;			bool		IsNull;			if (GistTupleIsInvalid(itvec[j]))				return FALSE;	/* signals that union with invalid tuple =>								 * result is invalid */			datum = index_getattr(itvec[j], i + 1, giststate->tupdesc, &IsNull);			if (IsNull)				continue;			gistdentryinit(giststate, i,						   evec->vector + evec->n,						   datum,						   NULL, NULL, (OffsetNumber) 0,						   FALSE, IsNull);			evec->n++;		}		/* If this tuple vector was all NULLs, the union is NULL */		if (evec->n == 0)		{			attr[i] = (Datum) 0;			isnull[i] = TRUE;		}		else		{			if (evec->n == 1)			{				evec->n = 2;				evec->vector[1] = evec->vector[0];			}			/* Make union and store in attr array */			attr[i] = FunctionCall2(&giststate->unionFn[i],									PointerGetDatum(evec),									PointerGetDatum(&attrsize));			isnull[i] = FALSE;		}	}	return TRUE;}/* * Return an IndexTuple containing the result of applying the "union" * method to the specified IndexTuple vector. */IndexTuplegistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate){	memset(isnullS, TRUE, sizeof(bool) * giststate->tupdesc->natts);	if (!gistMakeUnionItVec(giststate, itvec, len, 0, attrS, isnullS))		return gist_form_invalid_tuple(InvalidBlockNumber);	return gistFormTuple(giststate, r, attrS, isnullS, false);}/* * makes union of two key */voidgistMakeUnionKey(GISTSTATE *giststate, int attno,				 GISTENTRY *entry1, bool isnull1,				 GISTENTRY *entry2, bool isnull2,				 Datum *dst, bool *dstisnull){	int			dstsize;	static char storage[2 * sizeof(GISTENTRY) + GEVHDRSZ];	GistEntryVector *evec = (GistEntryVector *) storage;	evec->n = 2;	if (isnull1 && isnull2)	{		*dstisnull = TRUE;		*dst = (Datum) 0;	}	else	{		if (isnull1 == FALSE && isnull2 == FALSE)		{			evec->vector[0] = *entry1;			evec->vector[1] = *entry2;		}		else if (isnull1 == FALSE)		{			evec->vector[0] = *entry1;			evec->vector[1] = *entry1;		}		else		{			evec->vector[0] = *entry2;			evec->vector[1] = *entry2;		}		*dstisnull = FALSE;		*dst = FunctionCall2(&giststate->unionFn[attno],							 PointerGetDatum(evec),							 PointerGetDatum(&dstsize));	}}boolgistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b){	bool		result;	FunctionCall3(&giststate->equalFn[attno],				  a, b,				  PointerGetDatum(&result));	return result;}/* * Decompress all keys in tuple */voidgistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,				  OffsetNumber o, GISTENTRY *attdata, bool *isnull){	int			i;	for (i = 0; i < r->rd_att->natts; i++)	{		Datum		datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);		gistdentryinit(giststate, i, &attdata[i],					   datum, r, p, o,					   FALSE, isnull[i]);	}}/* * Forms union of oldtup and addtup, if union == oldtup then return NULL */IndexTuplegistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate){	bool		neednew = FALSE;	GISTENTRY	oldentries[INDEX_MAX_KEYS],				addentries[INDEX_MAX_KEYS];	bool		oldisnull[INDEX_MAX_KEYS],				addisnull[INDEX_MAX_KEYS];	IndexTuple	newtup = NULL;	int			i;	if (GistTupleIsInvalid(oldtup) || GistTupleIsInvalid(addtup))		return gist_form_invalid_tuple(ItemPointerGetBlockNumber(&(oldtup->t_tid)));	gistDeCompressAtt(giststate, r, oldtup, NULL,					  (OffsetNumber) 0, oldentries, oldisnull);	gistDeCompressAtt(giststate, r, addtup, NULL,					  (OffsetNumber) 0, addentries, addisnull);	for (i = 0; i < r->rd_att->natts; i++)	{		gistMakeUnionKey(giststate, i,

⌨️ 快捷键说明

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