#include "postgres.h"
#include "access/gist.h"
#include "access/skey.h"
#include "_int.h"
Go to the source code of this file.
Data Structures | |
struct | SPLITCOST |
Defines | |
#define | GETENTRY(vec, pos) ((ArrayType *) DatumGetPointer((vec)->vector[(pos)].key)) |
Functions | |
PG_FUNCTION_INFO_V1 (g_int_consistent) | |
PG_FUNCTION_INFO_V1 (g_int_compress) | |
PG_FUNCTION_INFO_V1 (g_int_decompress) | |
PG_FUNCTION_INFO_V1 (g_int_penalty) | |
PG_FUNCTION_INFO_V1 (g_int_picksplit) | |
PG_FUNCTION_INFO_V1 (g_int_union) | |
PG_FUNCTION_INFO_V1 (g_int_same) | |
Datum | g_int_consistent (PG_FUNCTION_ARGS) |
Datum | g_int_compress (PG_FUNCTION_ARGS) |
Datum | g_int_decompress (PG_FUNCTION_ARGS) |
Datum | g_int_penalty (PG_FUNCTION_ARGS) |
Datum | g_int_picksplit (PG_FUNCTION_ARGS) |
Datum | g_int_union (PG_FUNCTION_ARGS) |
Datum | g_int_same (PG_FUNCTION_ARGS) |
static int | comparecost (const void *a, const void *b) |
#define GETENTRY | ( | vec, | ||
pos | ||||
) | ((ArrayType *) DatumGetPointer((vec)->vector[(pos)].key)) |
Definition at line 11 of file _int_gist.c.
Referenced by g_int_picksplit(), and g_int_union().
static int comparecost | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 356 of file _int_gist.c.
Referenced by g_int_picksplit().
Datum g_int_compress | ( | PG_FUNCTION_ARGS | ) |
Definition at line 145 of file _int_gist.c.
References ARRISEMPTY, ARRNELEMS, ARRPTR, CHECKARRVALID, DatumGetArrayTypeP, DatumGetArrayTypePCopy, DatumGetPointer, elog, FALSE, gistentryinit, i, GISTENTRY::key, GISTENTRY::leafkey, MAXNUMRANGE, memmove, NOTICE, GISTENTRY::offset, GISTENTRY::page, palloc(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, PREPAREARR, GISTENTRY::rel, and resize_intArrayType().
{ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; ArrayType *r; int len; int *dr; int i, min, cand; if (entry->leafkey) { r = DatumGetArrayTypePCopy(entry->key); CHECKARRVALID(r); PREPAREARR(r); if (ARRNELEMS(r) >= 2 * MAXNUMRANGE) elog(NOTICE, "input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead", 2 * MAXNUMRANGE - 1, ARRNELEMS(r)); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } /* * leaf entries never compress one more time, only when entry->leafkey * ==true, so now we work only with internal keys */ r = DatumGetArrayTypeP(entry->key); CHECKARRVALID(r); if (ARRISEMPTY(r)) { if (r != (ArrayType *) DatumGetPointer(entry->key)) pfree(r); PG_RETURN_POINTER(entry); } if ((len = ARRNELEMS(r)) >= 2 * MAXNUMRANGE) { /* compress */ if (r == (ArrayType *) DatumGetPointer(entry->key)) r = DatumGetArrayTypePCopy(entry->key); r = resize_intArrayType(r, 2 * (len)); dr = ARRPTR(r); for (i = len - 1; i >= 0; i--) dr[2 * i] = dr[2 * i + 1] = dr[i]; len *= 2; cand = 1; while (len > MAXNUMRANGE * 2) { min = 0x7fffffff; for (i = 2; i < len; i += 2) if (min > (dr[i] - dr[i - 1])) { min = (dr[i] - dr[i - 1]); cand = i; } memmove((void *) &dr[cand - 1], (void *) &dr[cand + 1], (len - cand - 1) * sizeof(int32)); len -= 2; } r = resize_intArrayType(r, len); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } else PG_RETURN_POINTER(entry); }
Datum g_int_consistent | ( | PG_FUNCTION_ARGS | ) |
Definition at line 40 of file _int_gist.c.
References BooleanSearchStrategy, CHECKARRVALID, DatumGetPointer, DirectFunctionCall3, execconsistent(), g_int_same(), GIST_LEAF, inner_int_contains(), inner_int_overlap(), GISTENTRY::key, pfree(), PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_BOOL, PointerGetDatum, PREPAREARR, RTContainedByStrategyNumber, RTContainsStrategyNumber, RTOldContainedByStrategyNumber, RTOldContainsStrategyNumber, RTOverlapStrategyNumber, and RTSameStrategyNumber.
{ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); ArrayType *query = PG_GETARG_ARRAYTYPE_P_COPY(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ bool *recheck = (bool *) PG_GETARG_POINTER(4); bool retval; /* this is exact except for RTSameStrategyNumber */ *recheck = (strategy == RTSameStrategyNumber); if (strategy == BooleanSearchStrategy) { retval = execconsistent((QUERYTYPE *) query, (ArrayType *) DatumGetPointer(entry->key), GIST_LEAF(entry)); pfree(query); PG_RETURN_BOOL(retval); } /* sort query for fast search, key is already sorted */ CHECKARRVALID(query); PREPAREARR(query); switch (strategy) { case RTOverlapStrategyNumber: retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key), query); break; case RTSameStrategyNumber: if (GIST_LEAF(entry)) DirectFunctionCall3(g_int_same, entry->key, PointerGetDatum(query), PointerGetDatum(&retval)); else retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key), query); break; case RTContainsStrategyNumber: case RTOldContainsStrategyNumber: retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key), query); break; case RTContainedByStrategyNumber: case RTOldContainedByStrategyNumber: if (GIST_LEAF(entry)) retval = inner_int_contains(query, (ArrayType *) DatumGetPointer(entry->key)); else retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key), query); break; default: retval = FALSE; } pfree(query); PG_RETURN_BOOL(retval); }
Datum g_int_decompress | ( | PG_FUNCTION_ARGS | ) |
Definition at line 223 of file _int_gist.c.
References ARRISEMPTY, ARRNELEMS, ARRPTR, CHECKARRVALID, DatumGetArrayTypeP, DatumGetPointer, FALSE, gistentryinit, i, internal_size(), GISTENTRY::key, MAXNUMRANGE, new_intArrayType(), GISTENTRY::offset, GISTENTRY::page, palloc(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, and GISTENTRY::rel.
{ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; ArrayType *r; int *dr, lenr; ArrayType *in; int lenin; int *din; int i, j; in = DatumGetArrayTypeP(entry->key); CHECKARRVALID(in); if (ARRISEMPTY(in)) { if (in != (ArrayType *) DatumGetPointer(entry->key)) { retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(in), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } PG_RETURN_POINTER(entry); } lenin = ARRNELEMS(in); if (lenin < 2 * MAXNUMRANGE) { /* not compressed value */ if (in != (ArrayType *) DatumGetPointer(entry->key)) { retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(in), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } PG_RETURN_POINTER(entry); } din = ARRPTR(in); lenr = internal_size(din, lenin); r = new_intArrayType(lenr); dr = ARRPTR(r); for (i = 0; i < lenin; i += 2) for (j = din[i]; j <= din[i + 1]; j++) if ((!i) || *(dr - 1) != j) *dr++ = j; if (in != (ArrayType *) DatumGetPointer(entry->key)) pfree(in); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); }
Datum g_int_penalty | ( | PG_FUNCTION_ARGS | ) |
Definition at line 291 of file _int_gist.c.
References DatumGetPointer, inner_int_union(), GISTENTRY::key, pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, and rt__int_size().
{ GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); float *result = (float *) PG_GETARG_POINTER(2); ArrayType *ud; float tmp1, tmp2; ud = inner_int_union((ArrayType *) DatumGetPointer(origentry->key), (ArrayType *) DatumGetPointer(newentry->key)); rt__int_size(ud, &tmp1); rt__int_size((ArrayType *) DatumGetPointer(origentry->key), &tmp2); *result = tmp1 - tmp2; pfree(ud); PG_RETURN_POINTER(result); }
Datum g_int_picksplit | ( | PG_FUNCTION_ARGS | ) |
Definition at line 369 of file _int_gist.c.
References Abs, comparecost(), copy_intArrayType(), SPLITCOST::cost, DEBUG3, elog, FirstOffsetNumber, GETENTRY, i, inner_int_inter(), inner_int_union(), NODE::left, GistEntryVector::n, NULL, OffsetNumberNext, palloc(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, SPLITCOST::pos, qsort, NODE::right, rt__int_size(), GIST_SPLITVEC::spl_ldatum, GIST_SPLITVEC::spl_left, GIST_SPLITVEC::spl_nleft, GIST_SPLITVEC::spl_nright, GIST_SPLITVEC::spl_rdatum, GIST_SPLITVEC::spl_right, and WISH_F.
{ GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); OffsetNumber i, j; ArrayType *datum_alpha, *datum_beta; ArrayType *datum_l, *datum_r; ArrayType *union_d, *union_dl, *union_dr; ArrayType *inter_d; bool firsttime; float size_alpha, size_beta, size_union, size_inter; float size_waste, waste; float size_l, size_r; int nbytes; OffsetNumber seed_1 = 0, seed_2 = 0; OffsetNumber *left, *right; OffsetNumber maxoff; SPLITCOST *costvector; #ifdef GIST_DEBUG elog(DEBUG3, "--------picksplit %d", entryvec->n); #endif maxoff = entryvec->n - 2; nbytes = (maxoff + 2) * sizeof(OffsetNumber); v->spl_left = (OffsetNumber *) palloc(nbytes); v->spl_right = (OffsetNumber *) palloc(nbytes); firsttime = true; waste = 0.0; for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i)) { datum_alpha = GETENTRY(entryvec, i); for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j)) { datum_beta = GETENTRY(entryvec, j); /* compute the wasted space by unioning these guys */ /* size_waste = size_union - size_inter; */ union_d = inner_int_union(datum_alpha, datum_beta); rt__int_size(union_d, &size_union); inter_d = inner_int_inter(datum_alpha, datum_beta); rt__int_size(inter_d, &size_inter); size_waste = size_union - size_inter; pfree(union_d); if (inter_d != (ArrayType *) NULL) pfree(inter_d); /* * are these a more promising split that what we've already seen? */ if (size_waste > waste || firsttime) { waste = size_waste; seed_1 = i; seed_2 = j; firsttime = false; } } } left = v->spl_left; v->spl_nleft = 0; right = v->spl_right; v->spl_nright = 0; if (seed_1 == 0 || seed_2 == 0) { seed_1 = 1; seed_2 = 2; } datum_alpha = GETENTRY(entryvec, seed_1); datum_l = copy_intArrayType(datum_alpha); rt__int_size(datum_l, &size_l); datum_beta = GETENTRY(entryvec, seed_2); datum_r = copy_intArrayType(datum_beta); rt__int_size(datum_r, &size_r); maxoff = OffsetNumberNext(maxoff); /* * sort entries */ costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff); for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { costvector[i - 1].pos = i; datum_alpha = GETENTRY(entryvec, i); union_d = inner_int_union(datum_l, datum_alpha); rt__int_size(union_d, &size_alpha); pfree(union_d); union_d = inner_int_union(datum_r, datum_alpha); rt__int_size(union_d, &size_beta); pfree(union_d); costvector[i - 1].cost = Abs((size_alpha - size_l) - (size_beta - size_r)); } qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost); /* * Now split up the regions between the two seeds. An important property * of this split algorithm is that the split vector v has the indices of * items to be split in order in its left and right vectors. We exploit * this property by doing a merge in the code that actually splits the * page. * * For efficiency, we also place the new index tuple in this loop. This is * handled at the very end, when we have placed all the existing tuples * and i == maxoff + 1. */ for (j = 0; j < maxoff; j++) { i = costvector[j].pos; /* * If we've already decided where to place this item, just put it on * the right list. Otherwise, we need to figure out which page needs * the least enlargement in order to store the item. */ if (i == seed_1) { *left++ = i; v->spl_nleft++; continue; } else if (i == seed_2) { *right++ = i; v->spl_nright++; continue; } /* okay, which page needs least enlargement? */ datum_alpha = GETENTRY(entryvec, i); union_dl = inner_int_union(datum_l, datum_alpha); union_dr = inner_int_union(datum_r, datum_alpha); rt__int_size(union_dl, &size_alpha); rt__int_size(union_dr, &size_beta); /* pick which page to add it to */ if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.01)) { if (datum_l) pfree(datum_l); if (union_dr) pfree(union_dr); datum_l = union_dl; size_l = size_alpha; *left++ = i; v->spl_nleft++; } else { if (datum_r) pfree(datum_r); if (union_dl) pfree(union_dl); datum_r = union_dr; size_r = size_beta; *right++ = i; v->spl_nright++; } } pfree(costvector); *right = *left = FirstOffsetNumber; v->spl_ldatum = PointerGetDatum(datum_l); v->spl_rdatum = PointerGetDatum(datum_r); PG_RETURN_POINTER(v); }
Datum g_int_same | ( | PG_FUNCTION_ARGS | ) |
Definition at line 313 of file _int_gist.c.
References ARRNELEMS, ARRPTR, CHECKARRVALID, PG_GETARG_ARRAYTYPE_P, PG_GETARG_POINTER, and PG_RETURN_POINTER.
Referenced by g_int_consistent().
{ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0); ArrayType *b = PG_GETARG_ARRAYTYPE_P(1); bool *result = (bool *) PG_GETARG_POINTER(2); int32 n = ARRNELEMS(a); int32 *da, *db; CHECKARRVALID(a); CHECKARRVALID(b); if (n != ARRNELEMS(b)) { *result = false; PG_RETURN_POINTER(result); } *result = TRUE; da = ARRPTR(a); db = ARRPTR(b); while (n--) { if (*da++ != *db++) { *result = FALSE; break; } } PG_RETURN_POINTER(result); }
Datum g_int_union | ( | PG_FUNCTION_ARGS | ) |
Definition at line 105 of file _int_gist.c.
References _int_unique(), ARRNELEMS, ARRPTR, CHECKARRVALID, GETENTRY, i, GistEntryVector::n, new_intArrayType(), PG_GETARG_POINTER, PG_RETURN_POINTER, QSORT, and VARSIZE.
{ GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); int *size = (int *) PG_GETARG_POINTER(1); int32 i, *ptr; ArrayType *res; int totlen = 0; for (i = 0; i < entryvec->n; i++) { ArrayType *ent = GETENTRY(entryvec, i); CHECKARRVALID(ent); totlen += ARRNELEMS(ent); } res = new_intArrayType(totlen); ptr = ARRPTR(res); for (i = 0; i < entryvec->n; i++) { ArrayType *ent = GETENTRY(entryvec, i); int nel; nel = ARRNELEMS(ent); memcpy(ptr, ARRPTR(ent), nel * sizeof(int32)); ptr += nel; } QSORT(res, 1); res = _int_unique(res); *size = VARSIZE(res); PG_RETURN_POINTER(res); }
PG_FUNCTION_INFO_V1 | ( | g_int_penalty | ) |
PG_FUNCTION_INFO_V1 | ( | g_int_same | ) |
PG_FUNCTION_INFO_V1 | ( | g_int_picksplit | ) |
PG_FUNCTION_INFO_V1 | ( | g_int_decompress | ) |
PG_FUNCTION_INFO_V1 | ( | g_int_consistent | ) |
PG_FUNCTION_INFO_V1 | ( | g_int_compress | ) |
PG_FUNCTION_INFO_V1 | ( | g_int_union | ) |