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 + -
显示快捷键?