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

📄 gist.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
	GISTENTRY	entry,				identry[INDEX_MAX_KEYS];	bool		IsNull,				decompvec[INDEX_MAX_KEYS],				isnull[INDEX_MAX_KEYS];	int			j;	maxoff = PageGetMaxOffsetNumber(p);	*which_grow = -1.0;	which = -1;	sum_grow = 1;	gistDeCompressAtt(giststate, r,					  it, (Page) NULL, (OffsetNumber) 0,					  identry, decompvec, isnull);	for (i = FirstOffsetNumber; i <= maxoff && sum_grow; i = OffsetNumberNext(i))	{		IndexTuple	itup = (IndexTuple) PageGetItem(p, PageGetItemId(p, i));		sum_grow = 0;		for (j = 0; j < r->rd_att->natts; j++)		{			datum = index_getattr(itup, j + 1, giststate->tupdesc, &IsNull);			gistdentryinit(giststate, j, &entry, datum, r, p, i, ATTSIZE(datum, giststate->tupdesc, j + 1, IsNull), FALSE, IsNull);			gistpenalty(giststate, j, &entry, IsNull, &identry[j], isnull[j], &usize);			if ((!isAttByVal(giststate, j)) && entry.key != datum)				pfree(DatumGetPointer(entry.key));			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;			}		}	}	gistFreeAtt(r, identry, decompvec);	return which;}voidgistfreestack(GISTSTACK *s){	GISTSTACK  *p;	while (s != (GISTSTACK *) NULL)	{		p = s->gs_parent;		pfree(s);		s = p;	}}/* * Retail deletion of a single tuple. * * NB: this is no longer called externally, but is still needed by * gistlayerinsert().  That dependency will have to be fixed if GIST * is ever going to allow concurrent insertions. */static voidgistdelete(Relation r, ItemPointer tid){	BlockNumber blkno;	OffsetNumber offnum;	Buffer		buf;	Page		page;	/*	 * Since GIST is not marked "amconcurrent" in pg_am, caller should	 * have acquired exclusive lock on index relation.	We need no locking	 * here.	 */	blkno = ItemPointerGetBlockNumber(tid);	offnum = ItemPointerGetOffsetNumber(tid);	/* adjust any scans that will be affected by this deletion */	/* NB: this works only for scans in *this* backend! */	gistadjscans(r, GISTOP_DEL, blkno, offnum);	/* delete the index tuple */	buf = ReadBuffer(r, blkno);	page = BufferGetPage(buf);	PageIndexTupleDelete(page, offnum);	WriteBuffer(buf);}/* * Bulk deletion of all index entries pointing to a set of heap tuples. * The set of target tuples is specified via a callback routine that tells * whether any given heap tuple (identified by ItemPointer) is being deleted. * * Result: a palloc'd struct containing statistical info for VACUUM displays. */Datumgistbulkdelete(PG_FUNCTION_ARGS){	Relation	rel = (Relation) PG_GETARG_POINTER(0);	IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);	void	   *callback_state = (void *) PG_GETARG_POINTER(2);	IndexBulkDeleteResult *result;	BlockNumber num_pages;	double		tuples_removed;	double		num_index_tuples;	IndexScanDesc iscan;	tuples_removed = 0;	num_index_tuples = 0;	/*	 * Since GIST is not marked "amconcurrent" in pg_am, caller should	 * have acquired exclusive lock on index relation.	We need no locking	 * here.	 */	/*	 * XXX generic implementation --- should be improved!	 */	/* walk through the entire index */	iscan = index_beginscan(NULL, rel, SnapshotAny, 0, (ScanKey) NULL);	/* including killed tuples */	iscan->ignore_killed_tuples = false;	while (index_getnext_indexitem(iscan, ForwardScanDirection))	{		if (callback(&iscan->xs_ctup.t_self, callback_state))		{			ItemPointerData indextup = iscan->currentItemData;			BlockNumber blkno;			OffsetNumber offnum;			Buffer		buf;			Page		page;			blkno = ItemPointerGetBlockNumber(&indextup);			offnum = ItemPointerGetOffsetNumber(&indextup);			/* adjust any scans that will be affected by this deletion */			gistadjscans(rel, GISTOP_DEL, blkno, offnum);			/* delete the index tuple */			buf = ReadBuffer(rel, blkno);			page = BufferGetPage(buf);			PageIndexTupleDelete(page, offnum);			WriteBuffer(buf);			tuples_removed += 1;		}		else			num_index_tuples += 1;	}	index_endscan(iscan);	/* return statistics */	num_pages = RelationGetNumberOfBlocks(rel);	result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));	result->num_pages = num_pages;	result->num_index_tuples = num_index_tuples;	result->tuples_removed = tuples_removed;	PG_RETURN_POINTER(result);}voidinitGISTstate(GISTSTATE *giststate, Relation index){	int			i;	if (index->rd_att->natts > INDEX_MAX_KEYS)		elog(ERROR, "numberOfAttributes %d > %d",			 index->rd_att->natts, INDEX_MAX_KEYS);	giststate->tupdesc = index->rd_att;	for (i = 0; i < index->rd_att->natts; i++)	{		fmgr_info_copy(&(giststate->consistentFn[i]),				   index_getprocinfo(index, i + 1, GIST_CONSISTENT_PROC),					   CurrentMemoryContext);		fmgr_info_copy(&(giststate->unionFn[i]),					   index_getprocinfo(index, i + 1, GIST_UNION_PROC),					   CurrentMemoryContext);		fmgr_info_copy(&(giststate->compressFn[i]),					 index_getprocinfo(index, i + 1, GIST_COMPRESS_PROC),					   CurrentMemoryContext);		fmgr_info_copy(&(giststate->decompressFn[i]),				   index_getprocinfo(index, i + 1, GIST_DECOMPRESS_PROC),					   CurrentMemoryContext);		fmgr_info_copy(&(giststate->penaltyFn[i]),					   index_getprocinfo(index, i + 1, GIST_PENALTY_PROC),					   CurrentMemoryContext);		fmgr_info_copy(&(giststate->picksplitFn[i]),					index_getprocinfo(index, i + 1, GIST_PICKSPLIT_PROC),					   CurrentMemoryContext);		fmgr_info_copy(&(giststate->equalFn[i]),					   index_getprocinfo(index, i + 1, GIST_EQUAL_PROC),					   CurrentMemoryContext);	}}voidfreeGISTstate(GISTSTATE *giststate){	/* no work */}#ifdef GIST_PAGEADDITEM/*** Given an IndexTuple to be inserted on a page, this routine replaces** the key with another key, which may involve generating a new IndexTuple** if the sizes don't match or if the null status changes.**** XXX this only works for a single-column index tuple!*/static IndexTuplegist_tuple_replacekey(Relation r, GISTENTRY entry, IndexTuple t){	bool		IsNull;	Datum		datum = index_getattr(t, 1, r->rd_att, &IsNull);	/*	 * If new entry fits in index tuple, copy it in.  To avoid worrying	 * about null-value bitmask, pass it off to the general	 * index_formtuple routine if either the previous or new value is	 * NULL.	 */	if (!IsNull && DatumGetPointer(entry.key) != NULL &&		(Size) entry.bytes <= ATTSIZE(datum, r, 1, IsNull))	{		memcpy(DatumGetPointer(datum),			   DatumGetPointer(entry.key),			   entry.bytes);		/* clear out old size */		t->t_info &= ~INDEX_SIZE_MASK;		/* or in new size */		t->t_info |= MAXALIGN(entry.bytes + sizeof(IndexTupleData));		return t;	}	else	{		/* generate a new index tuple for the compressed entry */		TupleDesc	tupDesc = r->rd_att;		IndexTuple	newtup;		char		isnull;		isnull = DatumGetPointer(entry.key) != NULL ? ' ' : 'n';		newtup = (IndexTuple) index_formtuple(tupDesc,											  &(entry.key),											  &isnull);		newtup->t_tid = t->t_tid;		return newtup;	}}#endif/*** 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,			   int b, bool l, bool isNull){	if (b && !isNull)	{		GISTENTRY  *dep;		gistentryinit(*e, k, r, pg, o, b, 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->bytes, dep->leafkey);			pfree(dep);		}	}	else		gistentryinit(*e, (Datum) 0, r, pg, o, 0, l);}/*** initialize a GiST entry with a compressed version of key*/static voidgistcentryinit(GISTSTATE *giststate, int nkey,			   GISTENTRY *e, Datum k, Relation r,			   Page pg, OffsetNumber o, int b, bool l, bool isNull){	if (!isNull)	{		GISTENTRY  *cep;		gistentryinit(*e, k, r, pg, o, b, 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->bytes, cep->leafkey);			pfree(cep);		}	}	else		gistentryinit(*e, (Datum) 0, r, pg, o, 0, l);}static IndexTuplegistFormTuple(GISTSTATE *giststate, Relation r,			  Datum attdata[], int datumsize[], bool isnull[]){	IndexTuple	tup;	char		isnullchar[INDEX_MAX_KEYS];	bool		whatfree[INDEX_MAX_KEYS];	GISTENTRY	centry[INDEX_MAX_KEYS];	Datum		compatt[INDEX_MAX_KEYS];	int			j;	for (j = 0; j < r->rd_att->natts; j++)	{		if (isnull[j])		{			isnullchar[j] = 'n';			compatt[j] = (Datum) 0;			whatfree[j] = FALSE;		}		else		{			gistcentryinit(giststate, j, &centry[j], attdata[j],					   (Relation) NULL, (Page) NULL, (OffsetNumber) NULL,						   datumsize[j], FALSE, FALSE);			isnullchar[j] = ' ';			compatt[j] = centry[j].key;			if (!isAttByVal(giststate, j))			{				whatfree[j] = TRUE;				if (centry[j].key != attdata[j])					pfree(DatumGetPointer(attdata[j]));			}			else				whatfree[j] = FALSE;		}	}	tup = (IndexTuple) index_formtuple(giststate->tupdesc, compatt, isnullchar);	for (j = 0; j < r->rd_att->natts; j++)		if (whatfree[j])			pfree(DatumGetPointer(compatt[j]));	return tup;}static voidgistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,	OffsetNumber o, GISTENTRY attdata[], bool decompvec[], bool isnull[]){	int			i;	Datum		datum;	for (i = 0; i < r->rd_att->natts; i++)	{		datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);		gistdentryinit(giststate, i, &attdata[i],					   datum, r, p, o,					   ATTSIZE(datum, giststate->tupdesc, i + 1, isnull[i]), FALSE, isnull[i]);		if (isAttByVal(giststate, i))			decompvec[i] = FALSE;		else		{			if (attdata[i].key == datum || isnull[i])				decompvec[i] = FALSE;			else				decompvec[i] = TRUE;		}	}}static voidgistFreeAtt(Relation r, GISTENTRY attdata[], bool decompvec[]){	int			i;	for (i = 0; i < r->rd_att->natts; i++)		if (decompvec[i])			pfree(DatumGetPointer(attdata[i].key));}static voidgistpenalty(GISTSTATE *giststate, int attno,			GISTENTRY *key1, bool isNull1,			GISTENTRY *key2, bool isNull2, float *penalty){	if (giststate->penaltyFn[attno].fn_strict && (isNull1 || isNull2))		*penalty = 0.0;	else		FunctionCall3(&giststate->penaltyFn[attno],					  PointerGetDatum(key1),					  PointerGetDatum(key2),					  PointerGetDatum(penalty));}#ifdef GISTDEBUGstatic voidgist_dumptree(Relation r, int level, BlockNumber blk, OffsetNumber coff){	Buffer		buffer;	Page		page;	GISTPageOpaque opaque;	IndexTuple	which;	ItemId		iid;	OffsetNumber i,				maxoff;	BlockNumber cblk;	char	   *pred;	pred = (char *) palloc(sizeof(char) * level + 1);	MemSet(pred, '\t', level);	pred[level] = '\0';	buffer = ReadBuffer(r, blk);	page = (Page) BufferGetPage(buffer);	opaque = (GISTPageOpaque) PageGetSpecialPointer(page);	maxoff = PageGetMaxOffsetNumber(page);	elog(DEBUG4, "%sPage: %d %s blk: %d maxoff: %d free: %d", pred,		 coff, (opaque->flags & F_LEAF) ? "LEAF" : "INTE", (int) blk,		 (int) maxoff, PageGetFreeSpace(page));	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))	{		iid = PageGetItemId(page, i);		which = (IndexTuple) PageGetItem(page, iid);		cblk = ItemPointerGetBlockNumber(&(which->t_tid));#ifdef PRINTTUPLE		elog(DEBUG4, "%s  Tuple. blk: %d size: %d", pred, (int) cblk,			 IndexTupleSize(which));#endif		if (!(opaque->flags & F_LEAF))			gist_dumptree(r, level + 1, cblk, i);	}	ReleaseBuffer(buffer);	pfree(pred);}#endif   /* defined GISTDEBUG */voidgist_redo(XLogRecPtr lsn, XLogRecord *record){	elog(PANIC, "gist_redo: unimplemented");}voidgist_undo(XLogRecPtr lsn, XLogRecord *record){	elog(PANIC, "gist_undo: unimplemented");}voidgist_desc(char *buf, uint8 xl_info, char *rec){}

⌨️ 快捷键说明

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