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

📄 gistutil.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * gistutil.c *	  utilities routines for the postgres GiST index access method. * * * Portions Copyright (c) 1996-2005, 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.7 2005/09/22 20:44:36 momjian Exp $ *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/gist_private.h"#include "access/gistscan.h"#include "access/heapam.h"#include "catalog/index.h"#include "miscadmin.h"#include "storage/freespace.h"/* group flags ( in gistadjsubkey ) */#define LEFT_ADDED		0x01#define RIGHT_ADDED 0x02#define BOTH_ADDED		( LEFT_ADDED | RIGHT_ADDED )/* * This defines is only for shorter code, used in gistgetadjusted * and gistadjsubkey only */#define FILLITEM(evp, isnullkey, okey, okeyb, rkey, rkeyb)	 do { \	if (isnullkey) {											  \		gistentryinit((evp), rkey, r, NULL,						  \					  (OffsetNumber) 0, rkeyb, FALSE);			  \	} else {													  \		gistentryinit((evp), okey, r, NULL,						  \					  (OffsetNumber) 0, okeyb, FALSE);			  \	}															  \} while(0)#define FILLEV(isnull1, key1, key1b, isnull2, key2, key2b) do { \	FILLITEM(*ev0p, isnull1, key1, key1b, key2, key2b);		\	FILLITEM(*ev1p, isnull2, key2, key2b, key1, key1b);		\} while(0);static void gistpenalty(GISTSTATE *giststate, int attno,			GISTENTRY *key1, bool isNull1,			GISTENTRY *key2, bool isNull2, float *penalty);/* * 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, LP_USED);		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){	unsigned int size = 0;	int			i;	for (i = 0; i < len; i++)		size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);	return (PageGetFreeSpace(page) < size);}/* * Read buffer into itup vector */IndexTuple *gistextractbuffer(Buffer buffer, int *len /* out */ ){	OffsetNumber i,				maxoff;	IndexTuple *itvec;	Page		p = (Page) BufferGetPage(buffer);	maxoff = PageGetMaxOffsetNumber(p);	*len = maxoff;	itvec = palloc(sizeof(IndexTuple) * maxoff);	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))		itvec[i - 1] = (IndexTuple) PageGetItem(p, PageGetItemId(p, 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;}/* * 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){	Datum		attr[INDEX_MAX_KEYS];	bool		isnull[INDEX_MAX_KEYS];	GistEntryVector *evec;	int			i;	GISTENTRY	centry[INDEX_MAX_KEYS];	IndexTuple	res;	evec = (GistEntryVector *) palloc(((len == 1) ? 2 : len) * sizeof(GISTENTRY) + GEVHDRSZ);	for (i = 0; i < len; i++)		if (GistTupleIsInvalid(itvec[i]))			return gist_form_invalid_tuple(InvalidBlockNumber);	for (i = 0; i < r->rd_att->natts; i++)	{		Datum		datum;		int			j;		int			real_len;		real_len = 0;		for (j = 0; j < len; j++)		{			bool		IsNull;			datum = index_getattr(itvec[j], i + 1, giststate->tupdesc, &IsNull);			if (IsNull)				continue;			gistdentryinit(giststate, i,						   &(evec->vector[real_len]),						   datum,						   NULL, NULL, (OffsetNumber) 0,						   ATTSIZE(datum, giststate->tupdesc, i + 1, IsNull),						   FALSE, IsNull);			real_len++;		}		/* If this tuple vector was all NULLs, the union is NULL */		if (real_len == 0)		{			attr[i] = (Datum) 0;			isnull[i] = TRUE;		}		else		{			int			datumsize;			if (real_len == 1)			{				evec->n = 2;				gistentryinit(evec->vector[1],							  evec->vector[0].key, r, NULL,							  (OffsetNumber) 0, evec->vector[0].bytes, FALSE);			}			else				evec->n = real_len;			/* Compress the result of the union and store in attr array */			datum = FunctionCall2(&giststate->unionFn[i],								  PointerGetDatum(evec),								  PointerGetDatum(&datumsize));			gistcentryinit(giststate, i, &centry[i], datum,						   NULL, NULL, (OffsetNumber) 0,						   datumsize, FALSE, FALSE);			isnull[i] = FALSE;			attr[i] = centry[i].key;		}	}	res = index_form_tuple(giststate->tupdesc, attr, isnull);	GistTupleSetValid(res);	return res;}/* * Forms union of oldtup and addtup, if union == oldtup then return NULL */IndexTuplegistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate){	GistEntryVector *evec;	bool		neednew = false;	bool		isnull[INDEX_MAX_KEYS];	Datum		attr[INDEX_MAX_KEYS];	GISTENTRY	centry[INDEX_MAX_KEYS],				oldatt[INDEX_MAX_KEYS],				addatt[INDEX_MAX_KEYS],			   *ev0p,			   *ev1p;	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)));	evec = palloc(2 * sizeof(GISTENTRY) + GEVHDRSZ);	evec->n = 2;	ev0p = &(evec->vector[0]);	ev1p = &(evec->vector[1]);	gistDeCompressAtt(giststate, r, oldtup, NULL,					  (OffsetNumber) 0, oldatt, oldisnull);	gistDeCompressAtt(giststate, r, addtup, NULL,					  (OffsetNumber) 0, addatt, addisnull);	for (i = 0; i < r->rd_att->natts; i++)	{		if (oldisnull[i] && addisnull[i])		{			attr[i] = (Datum) 0;			isnull[i] = TRUE;		}		else		{			Datum		datum;			int			datumsize;			FILLEV(oldisnull[i], oldatt[i].key, oldatt[i].bytes,				   addisnull[i], addatt[i].key, addatt[i].bytes);			datum = FunctionCall2(&giststate->unionFn[i],								  PointerGetDatum(evec),								  PointerGetDatum(&datumsize));			if (oldisnull[i] || addisnull[i])			{				if (oldisnull[i])					neednew = true;			}			else			{				bool		result;				FunctionCall3(&giststate->equalFn[i],							  ev0p->key,							  datum,							  PointerGetDatum(&result));				if (!result)					neednew = true;			}			gistcentryinit(giststate, i, &centry[i], datum,						   NULL, NULL, (OffsetNumber) 0,						   datumsize, FALSE, FALSE);			attr[i] = centry[i].key;			isnull[i] = FALSE;		}	}	if (neednew)	{		/* need to update key */		newtup = index_form_tuple(giststate->tupdesc, attr, isnull);		newtup->t_tid = oldtup->t_tid;	}	return newtup;}voidgistunionsubkey(Relation r, GISTSTATE *giststate, IndexTuple *itvec, GIST_SPLITVEC *spl, bool isall){	int			lr;	for (lr = 0; lr < 2; lr++)	{		OffsetNumber *entries;		int			i;		Datum	   *attr;		int			len,				   *attrsize;		bool	   *isnull;		GistEntryVector *evec;		if (lr)		{			attrsize = spl->spl_lattrsize;			attr = spl->spl_lattr;			len = spl->spl_nleft;			entries = spl->spl_left;			isnull = spl->spl_lisnull;		}		else		{			attrsize = spl->spl_rattrsize;			attr = spl->spl_rattr;			len = spl->spl_nright;			entries = spl->spl_right;			isnull = spl->spl_risnull;		}		evec = palloc(((len < 2) ? 2 : len) * sizeof(GISTENTRY) + GEVHDRSZ);		for (i = (isall) ? 0 : 1; i < r->rd_att->natts; i++)		{			int			j;			Datum		datum;			int			datumsize;			int			real_len;			real_len = 0;			for (j = 0; j < len; j++)			{				bool		IsNull;				if (spl->spl_idgrp[entries[j]])					continue;				datum = index_getattr(itvec[entries[j] - 1], i + 1,									  giststate->tupdesc, &IsNull);				if (IsNull)					continue;				gistdentryinit(giststate, i,							   &(evec->vector[real_len]),							   datum,							   NULL, NULL, (OffsetNumber) 0,						   ATTSIZE(datum, giststate->tupdesc, i + 1, IsNull),							   FALSE, IsNull);				real_len++;			}			if (real_len == 0)			{				datum = (Datum) 0;				datumsize = 0;				isnull[i] = true;			}			else			{				/*				 * evec->vector[0].bytes may be not defined, so form union				 * with itself				 */				if (real_len == 1)				{					evec->n = 2;					memcpy(&(evec->vector[1]), &(evec->vector[0]),						   sizeof(GISTENTRY));				}				else					evec->n = real_len;				datum = FunctionCall2(&giststate->unionFn[i],									  PointerGetDatum(evec),									  PointerGetDatum(&datumsize));				isnull[i] = false;			}			attr[i] = datum;			attrsize[i] = datumsize;		}	}}/* * find group in vector with equal value */intgistfindgroup(GISTSTATE *giststate, GISTENTRY *valvec, GIST_SPLITVEC *spl){	int			i;	int			curid = 1;	/*	 * first key is always not null (see gistinsert), so we may not check for	 * nulls	 */	for (i = 0; i < spl->spl_nleft; i++)	{		int			j;		int			len;		bool		result;		if (spl->spl_idgrp[spl->spl_left[i]])			continue;		len = 0;		/* find all equal value in right part */		for (j = 0; j < spl->spl_nright; j++)		{			if (spl->spl_idgrp[spl->spl_right[j]])				continue;			FunctionCall3(&giststate->equalFn[0],						  valvec[spl->spl_left[i]].key,						  valvec[spl->spl_right[j]].key,						  PointerGetDatum(&result));			if (result)			{				spl->spl_idgrp[spl->spl_right[j]] = curid;				len++;			}		}		/* find all other equal value in left part */		if (len)		{			/* add current val to list of equal values */			spl->spl_idgrp[spl->spl_left[i]] = curid;			/* searching .. */			for (j = i + 1; j < spl->spl_nleft; j++)			{				if (spl->spl_idgrp[spl->spl_left[j]])					continue;				FunctionCall3(&giststate->equalFn[0],							  valvec[spl->spl_left[i]].key,							  valvec[spl->spl_left[j]].key,							  PointerGetDatum(&result));				if (result)				{					spl->spl_idgrp[spl->spl_left[j]] = curid;					len++;				}			}			spl->spl_ngrp[curid] = len + 1;			curid++;		}	}

⌨️ 快捷键说明

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