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

📄 gist.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
		}		/* key is modified, so old version must be deleted */		ItemPointerSet(&oldtid, blkno, child);		gistdelete(r, &oldtid);		/*		 * if child was splitted, new key for child will be inserted in		 * the end list of child, so we must say to any scans that page is		 * changed beginning from 'child' offset		 */		if (ret & SPLITED)			gistadjscans(r, GISTOP_SPLIT, blkno, child);	}	ret = INSERTED;	if (gistnospace(page, (*itup), *len))	{		/* no space for insertion */		IndexTuple *itvec,				   *newitup;		int			tlen,					oldlen;		ret |= SPLITED;		itvec = gistreadbuffer(buffer, &tlen);		itvec = gistjoinvector(itvec, &tlen, (*itup), *len);		oldlen = *len;		newitup = gistSplit(r, buffer, itvec, &tlen, giststate,							(opaque->flags & F_LEAF) ? res : NULL);		/* res only for																		 * inserting in leaf */		ReleaseBuffer(buffer);		do			pfree((*itup)[oldlen - 1]);		while ((--oldlen) > 0);		pfree((*itup));		pfree(itvec);		*itup = newitup;		*len = tlen;			/* now tlen >= 2 */	}	else	{		/* enogth space */		OffsetNumber off,					l;		off = (PageIsEmpty(page)) ?			FirstOffsetNumber			:			OffsetNumberNext(PageGetMaxOffsetNumber(page));		l = gistwritebuffer(r, page, (*itup), *len, off);		WriteBuffer(buffer);		/*		 * set res if insert into leaf page, in this case, len = 1 always		 */		if (res && (opaque->flags & F_LEAF))			ItemPointerSet(&((*res)->pointerData), blkno, l);		if (*len > 1)		{						/* previous insert ret & SPLITED != 0 */			int			i;			/*			 * child was splited, so we must form union for insertion in			 * parent			 */			IndexTuple	newtup = gistunion(r, (*itup), *len, giststate);			ItemPointerSet(&(newtup->t_tid), blkno, 1);			for (i = 0; i < *len; i++)				pfree((*itup)[i]);			(*itup)[0] = newtup;			*len = 1;		}	}	return ret;}/* * Write itup vector to page, has no control of free space */static OffsetNumbergistwritebuffer(Relation r, Page page, IndexTuple *itup,				int len, OffsetNumber off){	OffsetNumber l = InvalidOffsetNumber;	int			i;#ifdef GIST_PAGEADDITEM	GISTENTRY	tmpdentry;	IndexTuple	newtup;	bool		IsNull;#endif	for (i = 0; i < len; i++)	{#ifdef GIST_PAGEADDITEM		l = gistPageAddItem(giststate, r, page,							(Item) itup[i], IndexTupleSize(itup[i]),							off, LP_USED, &tmpdentry, &newtup);		off = OffsetNumberNext(off);		if (DatumGetPointer(tmpdentry.key) != NULL &&		  tmpdentry.key != index_getattr(itup[i], 1, r->rd_att, &IsNull))			pfree(DatumGetPointer(tmpdentry.key));		if (itup[i] != newtup)			pfree(newtup);#else		l = PageAddItem(page, (Item) itup[i], IndexTupleSize(itup[i]),						off, LP_USED);		if (l == InvalidOffsetNumber)			elog(ERROR, "failed to add index item to \"%s\"",				 RelationGetRelationName(r));#endif	}	return l;}/* * Check space for itup vector on page */static intgistnospace(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 */static IndexTuple *gistreadbuffer(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 */static 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 union of itup vector */static IndexTuplegistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate){	Datum		attr[INDEX_MAX_KEYS];	bool		whatfree[INDEX_MAX_KEYS];	char		isnull[INDEX_MAX_KEYS];	char	   *storage;	bytea	   *evec;	Datum		datum;	int			datumsize,				i,				j;	GISTENTRY	centry[INDEX_MAX_KEYS];	bool	   *needfree;	IndexTuple	newtup;	bool		IsNull;	int			reallen;	needfree = (bool *) palloc(((len == 1) ? 2 : len) * sizeof(bool));	/* workaround for 64-bit: ensure GISTENTRY array is maxaligned */	storage = (char *) palloc(((len == 1) ? 2 : len) * sizeof(GISTENTRY) + MAXALIGN(VARHDRSZ));	evec = (bytea *) (storage + MAXALIGN(VARHDRSZ) - VARHDRSZ);	for (j = 0; j < r->rd_att->natts; j++)	{		reallen = 0;		for (i = 0; i < len; i++)		{			datum = index_getattr(itvec[i], j + 1, giststate->tupdesc, &IsNull);			if (IsNull)				continue;			gistdentryinit(giststate, j,						   &((GISTENTRY *) VARDATA(evec))[reallen],						   datum,					   (Relation) NULL, (Page) NULL, (OffsetNumber) NULL,						   ATTSIZE(datum, giststate->tupdesc, j + 1, IsNull), FALSE, IsNull);			if ((!isAttByVal(giststate, j)) &&				((GISTENTRY *) VARDATA(evec))[reallen].key != datum)				needfree[reallen] = TRUE;			else				needfree[reallen] = FALSE;			reallen++;		}		if (reallen == 0)		{			attr[j] = (Datum) 0;			isnull[j] = 'n';			whatfree[j] = FALSE;		}		else		{			if (reallen == 1)			{				VARATT_SIZEP(evec) = 2 * sizeof(GISTENTRY) + VARHDRSZ;				gistentryinit(((GISTENTRY *) VARDATA(evec))[1],					((GISTENTRY *) VARDATA(evec))[0].key, r, (Page) NULL,							  (OffsetNumber) 0, ((GISTENTRY *) VARDATA(evec))[0].bytes, FALSE);			}			else				VARATT_SIZEP(evec) = reallen * sizeof(GISTENTRY) + VARHDRSZ;			datum = FunctionCall2(&giststate->unionFn[j],								  PointerGetDatum(evec),								  PointerGetDatum(&datumsize));			for (i = 0; i < reallen; i++)				if (needfree[i])					pfree(DatumGetPointer(((GISTENTRY *) VARDATA(evec))[i].key));			gistcentryinit(giststate, j, &centry[j], datum,					   (Relation) NULL, (Page) NULL, (OffsetNumber) NULL,						   datumsize, FALSE, FALSE);			isnull[j] = ' ';			attr[j] = centry[j].key;			if (!isAttByVal(giststate, j))			{				whatfree[j] = TRUE;				if (centry[j].key != datum)					pfree(DatumGetPointer(datum));			}			else				whatfree[j] = FALSE;		}	}	pfree(storage);				/* pfree(evec); */	pfree(needfree);	newtup = (IndexTuple) index_formtuple(giststate->tupdesc, attr, isnull);	for (j = 0; j < r->rd_att->natts; j++)		if (whatfree[j])			pfree(DatumGetPointer(attr[j]));	return newtup;}/* * Forms union of oldtup and addtup, if union == oldtup then return NULL */static IndexTuplegistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate){	bytea	   *evec;	Datum		datum;	int			datumsize;	bool		result,				neednew = false;	char		isnull[INDEX_MAX_KEYS],				whatfree[INDEX_MAX_KEYS];	Datum		attr[INDEX_MAX_KEYS];	GISTENTRY	centry[INDEX_MAX_KEYS],				oldatt[INDEX_MAX_KEYS],				addatt[INDEX_MAX_KEYS],			   *ev0p,			   *ev1p;	bool		olddec[INDEX_MAX_KEYS],				adddec[INDEX_MAX_KEYS];	bool		oldisnull[INDEX_MAX_KEYS],				addisnull[INDEX_MAX_KEYS];	IndexTuple	newtup = NULL;	char	   *storage;	int			j;	/* workaround for 64-bit: ensure GISTENTRY array is maxaligned */	storage = (char *) palloc(2 * sizeof(GISTENTRY) + MAXALIGN(VARHDRSZ));	evec = (bytea *) (storage + MAXALIGN(VARHDRSZ) - VARHDRSZ);	VARATT_SIZEP(evec) = 2 * sizeof(GISTENTRY) + VARHDRSZ;	ev0p = &((GISTENTRY *) VARDATA(evec))[0];	ev1p = &((GISTENTRY *) VARDATA(evec))[1];	gistDeCompressAtt(giststate, r, oldtup, (Page) NULL,					  (OffsetNumber) 0, oldatt, olddec, oldisnull);	gistDeCompressAtt(giststate, r, addtup, (Page) NULL,					  (OffsetNumber) 0, addatt, adddec, addisnull);	for (j = 0; j < r->rd_att->natts; j++)	{		if (oldisnull[j] && addisnull[j])		{			isnull[j] = 'n';			attr[j] = (Datum) 0;			whatfree[j] = FALSE;		}		else		{			FILLEV(				   oldisnull[j], oldatt[j].key, oldatt[j].bytes,				   addisnull[j], addatt[j].key, addatt[j].bytes				);			datum = FunctionCall2(&giststate->unionFn[j],								  PointerGetDatum(evec),								  PointerGetDatum(&datumsize));			if (oldisnull[j] || addisnull[j])			{				if (oldisnull[j])					neednew = true;			}			else			{				FunctionCall3(&giststate->equalFn[j],							  ev0p->key,							  datum,							  PointerGetDatum(&result));				if (!result)					neednew = true;			}			if (olddec[j])				pfree(DatumGetPointer(oldatt[j].key));			if (adddec[j])				pfree(DatumGetPointer(addatt[j].key));			gistcentryinit(giststate, j, &centry[j], datum,					   (Relation) NULL, (Page) NULL, (OffsetNumber) NULL,						   datumsize, FALSE, FALSE);			isnull[j] = ' ';			attr[j] = centry[j].key;			if ((!isAttByVal(giststate, j)))			{				whatfree[j] = TRUE;				if (centry[j].key != datum)					pfree(DatumGetPointer(datum));			}			else				whatfree[j] = FALSE;		}	}	pfree(storage);				/* pfree(evec); */	if (neednew)	{		/* need to update key */		newtup = (IndexTuple) index_formtuple(giststate->tupdesc, attr, isnull);		newtup->t_tid = oldtup->t_tid;	}	for (j = 0; j < r->rd_att->natts; j++)		if (whatfree[j])			pfree(DatumGetPointer(attr[j]));	return newtup;}static voidgistunionsubkey(Relation r, GISTSTATE *giststate, IndexTuple *itvec, GIST_SPLITVEC *spl){	int			i,				j,				lr;	Datum	   *attr;	bool	   *needfree,				IsNull;	int			len,			   *attrsize;	OffsetNumber *entries;	bytea	   *evec;	char	   *storage;	Datum		datum;	int			datumsize;	int			reallen;	bool	   *isnull;	for (lr = 0; lr <= 1; lr++)	{		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;		}		needfree = (bool *) palloc(((len == 1) ? 2 : len) * sizeof(bool));		/* workaround for 64-bit: ensure GISTENTRY array is maxaligned */		storage = (char *) palloc(((len == 1) ? 2 : len) * sizeof(GISTENTRY) + MAXALIGN(VARHDRSZ));		evec = (bytea *) (storage + MAXALIGN(VARHDRSZ) - VARHDRSZ);		for (j = 1; j < r->rd_att->natts; j++)		{			reallen = 0;			for (i = 0; i < len; i++)			{				if (spl->spl_idgrp[entries[i]])					continue;				datum = index_getattr(itvec[entries[i] - 1], j + 1,									  giststate->tupdesc, &IsNull);				if (IsNull)					continue;				gistdentryinit(giststate, j,							   &((GISTENTRY *) VARDATA(evec))[reallen],							   datum,							   (Relation) NULL, (Page) NULL,							   (OffsetNumber) NULL,							   ATTSIZE(datum, giststate->tupdesc, j + 1, IsNull), FALSE, IsNull);				if ((!isAttByVal(giststate, j)) &&					((GISTENTRY *) VARDATA(evec))[reallen].key != datum)					needfree[reallen] = TRUE;				else					needfree[reallen] = FALSE;				reallen++;			}			if (reallen == 0)			{				datum = (Datum) 0;				datumsize = 0;				isnull[j] = true;			}			else			{				/*				 * ((GISTENTRY *) VARDATA(evec))[0].bytes may be not				 * defined, so form union with itself				 */				if (reallen == 1)				{					VARATT_SIZEP(evec) = 2 * sizeof(GISTENTRY) + VARHDRSZ;					memcpy((void *) &((GISTENTRY *) VARDATA(evec))[1],						   (void *) &((GISTENTRY *) VARDATA(evec))[0],						   sizeof(GISTENTRY));				}				else					VARATT_SIZEP(evec) = reallen * sizeof(GISTENTRY) + VARHDRSZ;				datum = FunctionCall2(&giststate->unionFn[j],									  PointerGetDatum(evec),									  PointerGetDatum(&datumsize));				isnull[j] = false;			}			for (i = 0; i < reallen; i++)				if (needfree[i])					pfree(DatumGetPointer(((GISTENTRY *) VARDATA(evec))[i].key));			attr[j] = datum;			attrsize[j] = datumsize;		}		pfree(storage);			/* pfree(evec); */		pfree(needfree);	}}/* * find group in vector with equial value */

⌨️ 快捷键说明

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