📄 gistutil.c
字号:
return curid;}/* * Insert equivalent tuples to left or right page with minimum * penalty */voidgistadjsubkey(Relation r, IndexTuple *itup, /* contains compressed entry */ int len, GIST_SPLITVEC *v, GISTSTATE *giststate){ int curlen; OffsetNumber *curwpos; GISTENTRY entry, identry[INDEX_MAX_KEYS], *ev0p, *ev1p; float lpenalty, rpenalty; GistEntryVector *evec; int datumsize; bool isnull[INDEX_MAX_KEYS]; int i, j; /* clear vectors */ curlen = v->spl_nleft; curwpos = v->spl_left; for (i = 0; i < v->spl_nleft; i++) { if (v->spl_idgrp[v->spl_left[i]] == 0) { *curwpos = v->spl_left[i]; curwpos++; } else curlen--; } v->spl_nleft = curlen; curlen = v->spl_nright; curwpos = v->spl_right; for (i = 0; i < v->spl_nright; i++) { if (v->spl_idgrp[v->spl_right[i]] == 0) { *curwpos = v->spl_right[i]; curwpos++; } else curlen--; } v->spl_nright = curlen; evec = palloc(2 * sizeof(GISTENTRY) + GEVHDRSZ); evec->n = 2; ev0p = &(evec->vector[0]); ev1p = &(evec->vector[1]); /* add equivalent tuple */ for (i = 0; i < len; i++) { Datum datum; if (v->spl_idgrp[i + 1] == 0) /* already inserted */ continue; gistDeCompressAtt(giststate, r, itup[i], NULL, (OffsetNumber) 0, identry, isnull); v->spl_ngrp[v->spl_idgrp[i + 1]]--; if (v->spl_ngrp[v->spl_idgrp[i + 1]] == 0 && (v->spl_grpflag[v->spl_idgrp[i + 1]] & BOTH_ADDED) != BOTH_ADDED) { /* force last in group */ rpenalty = 1.0; lpenalty = (v->spl_grpflag[v->spl_idgrp[i + 1]] & LEFT_ADDED) ? 2.0 : 0.0; } else { /* where? */ for (j = 1; j < r->rd_att->natts; j++) { gistentryinit(entry, v->spl_lattr[j], r, NULL, (OffsetNumber) 0, v->spl_lattrsize[j], FALSE); gistpenalty(giststate, j, &entry, v->spl_lisnull[j], &identry[j], isnull[j], &lpenalty); gistentryinit(entry, v->spl_rattr[j], r, NULL, (OffsetNumber) 0, v->spl_rattrsize[j], FALSE); gistpenalty(giststate, j, &entry, v->spl_risnull[j], &identry[j], isnull[j], &rpenalty); if (lpenalty != rpenalty) break; } } /* * add XXX: refactor this to avoid duplicating code */ if (lpenalty < rpenalty) { v->spl_grpflag[v->spl_idgrp[i + 1]] |= LEFT_ADDED; v->spl_left[v->spl_nleft] = i + 1; v->spl_nleft++; for (j = 1; j < r->rd_att->natts; j++) { if (isnull[j] && v->spl_lisnull[j]) { v->spl_lattr[j] = (Datum) 0; v->spl_lattrsize[j] = 0; } else { FILLEV(v->spl_lisnull[j], v->spl_lattr[j], v->spl_lattrsize[j], isnull[j], identry[j].key, identry[j].bytes); datum = FunctionCall2(&giststate->unionFn[j], PointerGetDatum(evec), PointerGetDatum(&datumsize)); v->spl_lattr[j] = datum; v->spl_lattrsize[j] = datumsize; v->spl_lisnull[j] = false; } } } else { v->spl_grpflag[v->spl_idgrp[i + 1]] |= RIGHT_ADDED; v->spl_right[v->spl_nright] = i + 1; v->spl_nright++; for (j = 1; j < r->rd_att->natts; j++) { if (isnull[j] && v->spl_risnull[j]) { v->spl_rattr[j] = (Datum) 0; v->spl_rattrsize[j] = 0; } else { FILLEV(v->spl_risnull[j], v->spl_rattr[j], v->spl_rattrsize[j], isnull[j], identry[j].key, identry[j].bytes); datum = FunctionCall2(&giststate->unionFn[j], PointerGetDatum(evec), PointerGetDatum(&datumsize)); v->spl_rattr[j] = datum; v->spl_rattrsize[j] = datumsize; v->spl_risnull[j] = false; } } } }}/* * find entry with lowest penalty */OffsetNumbergistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */ GISTSTATE *giststate){ OffsetNumber maxoff; OffsetNumber i; OffsetNumber which; float sum_grow, which_grow[INDEX_MAX_KEYS]; GISTENTRY entry, identry[INDEX_MAX_KEYS]; bool isnull[INDEX_MAX_KEYS]; maxoff = PageGetMaxOffsetNumber(p); *which_grow = -1.0; which = InvalidOffsetNumber; sum_grow = 1; gistDeCompressAtt(giststate, r, it, NULL, (OffsetNumber) 0, identry, isnull); for (i = FirstOffsetNumber; i <= maxoff && sum_grow; i = OffsetNumberNext(i)) { int j; IndexTuple itup = (IndexTuple) PageGetItem(p, PageGetItemId(p, i)); if (!GistPageIsLeaf(p) && GistTupleIsInvalid(itup)) { ereport(LOG, (errmsg("index \"%s\" needs VACUUM or REINDEX to finish crash recovery", RelationGetRelationName(r)))); continue; } sum_grow = 0; for (j = 0; j < r->rd_att->natts; j++) { Datum datum; float usize; bool IsNull; 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 (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; } } } if (which == InvalidOffsetNumber) which = FirstOffsetNumber; return which;}/* * 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); } else gistentryinit(*e, (Datum) 0, r, pg, o, 0, l);}/* * initialize a GiST entry with a compressed version of key */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); } else gistentryinit(*e, (Datum) 0, r, pg, o, 0, l);}IndexTuplegistFormTuple(GISTSTATE *giststate, Relation r, Datum attdata[], int datumsize[], bool isnull[]){ GISTENTRY centry[INDEX_MAX_KEYS]; Datum compatt[INDEX_MAX_KEYS]; int i; IndexTuple res; for (i = 0; i < r->rd_att->natts; i++) { if (isnull[i]) compatt[i] = (Datum) 0; else { gistcentryinit(giststate, i, ¢ry[i], attdata[i], NULL, NULL, (OffsetNumber) 0, datumsize[i], FALSE, FALSE); compatt[i] = centry[i].key; } } res = index_form_tuple(giststate->tupdesc, compatt, isnull); GistTupleSetValid(res); return res;}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, ATTSIZE(datum, giststate->tupdesc, i + 1, isnull[i]), FALSE, isnull[i]); }}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));}voidGISTInitBuffer(Buffer b, uint32 f){ GISTPageOpaque opaque; Page page; Size pageSize; pageSize = BufferGetPageSize(b); page = BufferGetPage(b); PageInit(page, pageSize, sizeof(GISTPageOpaqueData)); opaque = GistPageGetOpaque(page); opaque->flags = f; opaque->rightlink = InvalidBlockNumber; memset(&(opaque->nsn), 0, sizeof(GistNSN));}voidgistUserPicksplit(Relation r, GistEntryVector *entryvec, GIST_SPLITVEC *v, IndexTuple *itup, int len, GISTSTATE *giststate){ /* * now let the user-defined picksplit function set up the split vector; in * entryvec have no null value!! */ FunctionCall2(&giststate->picksplitFn[0], PointerGetDatum(entryvec), PointerGetDatum(v)); /* compatibility with old code */ if (v->spl_left[v->spl_nleft - 1] == InvalidOffsetNumber) v->spl_left[v->spl_nleft - 1] = (OffsetNumber) (entryvec->n - 1); if (v->spl_right[v->spl_nright - 1] == InvalidOffsetNumber) v->spl_right[v->spl_nright - 1] = (OffsetNumber) (entryvec->n - 1); v->spl_lattr[0] = v->spl_ldatum; v->spl_rattr[0] = v->spl_rdatum; v->spl_lisnull[0] = false; v->spl_risnull[0] = false; /* * if index is multikey, then we must to try get smaller bounding box for * subkey(s) */ if (r->rd_att->natts > 1) { int MaxGrpId; v->spl_idgrp = (int *) palloc0(sizeof(int) * entryvec->n); v->spl_grpflag = (char *) palloc0(sizeof(char) * entryvec->n); v->spl_ngrp = (int *) palloc(sizeof(int) * entryvec->n); MaxGrpId = gistfindgroup(giststate, entryvec->vector, v); /* form union of sub keys for each page (l,p) */ gistunionsubkey(r, giststate, itup, v, false); /* * if possible, we insert equivalent tuples with control by penalty * for a subkey(s) */ if (MaxGrpId > 1) gistadjsubkey(r, itup, len, v, giststate); }}BuffergistNewBuffer(Relation r){ Buffer buffer = InvalidBuffer; bool needLock; while (true) { BlockNumber blkno = GetFreeIndexPage(&r->rd_node); if (blkno == InvalidBlockNumber) break; buffer = ReadBuffer(r, blkno); if (ConditionalLockBuffer(buffer)) { Page page = BufferGetPage(buffer); if (GistPageIsDeleted(page)) { GistPageSetNonDeleted(page); return buffer; } else LockBuffer(buffer, GIST_UNLOCK); } ReleaseBuffer(buffer); } needLock = !RELATION_IS_LOCAL(r); if (needLock) LockRelationForExtension(r, ExclusiveLock); buffer = ReadBuffer(r, P_NEW); LockBuffer(buffer, GIST_EXCLUSIVE); if (needLock) UnlockRelationForExtension(r, ExclusiveLock); return buffer;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -