📄 gist.c
字号:
} /* 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, ¢ry[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, ¢ry[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 + -