typedef struct
{
- Datum *attr;
- int len;
OffsetNumber *entries;
+ int len;
+ Datum *attr;
bool *isnull;
bool *equiv;
} GistSplitUnion;
/*
- * Forms unions of subkeys after page split, but
- * uses only tuples aren't in groups of equalent tuples
+ * Form unions of subkeys after a page split, ignoring any tuples
+ * that are marked in gsvp->equiv[]
*/
static void
gistunionsubkeyvec(GISTSTATE *giststate, IndexTuple *itvec,
- GistSplitUnion *gsvp, int startkey)
+ GistSplitUnion *gsvp)
{
IndexTuple *cleanedItVec;
int i,
cleanedItVec[cleanedLen++] = itvec[gsvp->entries[i] - 1];
}
- gistMakeUnionItVec(giststate, cleanedItVec, cleanedLen, startkey,
+ gistMakeUnionItVec(giststate, cleanedItVec, cleanedLen,
gsvp->attr, gsvp->isnull);
pfree(cleanedItVec);
}
/*
- * unions subkeys for after user picksplit over attno-1 column
+ * Recompute unions of subkeys after a page split, ignoring any tuples
+ * that are marked in spl->spl_equiv[]
*/
static void
-gistunionsubkey(GISTSTATE *giststate, IndexTuple *itvec, GistSplitVector *spl, int attno)
+gistunionsubkey(GISTSTATE *giststate, IndexTuple *itvec, GistSplitVector *spl)
{
GistSplitUnion gsvp;
gsvp.equiv = spl->spl_equiv;
- gsvp.attr = spl->spl_lattr;
- gsvp.len = spl->splitVector.spl_nleft;
gsvp.entries = spl->splitVector.spl_left;
+ gsvp.len = spl->splitVector.spl_nleft;
+ gsvp.attr = spl->spl_lattr;
gsvp.isnull = spl->spl_lisnull;
- gistunionsubkeyvec(giststate, itvec, &gsvp, attno);
+ gistunionsubkeyvec(giststate, itvec, &gsvp);
- gsvp.attr = spl->spl_rattr;
- gsvp.len = spl->splitVector.spl_nright;
gsvp.entries = spl->splitVector.spl_right;
+ gsvp.len = spl->splitVector.spl_nright;
+ gsvp.attr = spl->spl_rattr;
gsvp.isnull = spl->spl_risnull;
- gistunionsubkeyvec(giststate, itvec, &gsvp, attno);
+ gistunionsubkeyvec(giststate, itvec, &gsvp);
}
/*
*/
if (LenEquiv == 0)
{
- gistunionsubkey(giststate, itup, v, attno + 1);
+ gistunionsubkey(giststate, itup, v);
}
else
{
cleanupOffsets(sv->spl_left, &sv->spl_nleft, v->spl_equiv, &LenEquiv);
cleanupOffsets(sv->spl_right, &sv->spl_nright, v->spl_equiv, &LenEquiv);
- gistunionsubkey(giststate, itup, v, attno + 1);
+ gistunionsubkey(giststate, itup, v);
if (LenEquiv == 1)
{
/*
* performance, because it's very rarely
*/
v->spl_equiv = NULL;
- gistunionsubkey(giststate, itup, v, attno + 1);
+ gistunionsubkey(giststate, itup, v);
return false;
}
v->splitVector.spl_left[v->splitVector.spl_nleft++] = i;
v->spl_equiv = NULL;
- gistunionsubkey(giststate, itup, v, attno);
+ gistunionsubkey(giststate, itup, v);
}
else
{
v->splitVector = backupSplit;
/* reunion left and right datums */
- gistunionsubkey(giststate, itup, v, attno);
+ gistunionsubkey(giststate, itup, v);
}
}
}
#include "storage/bufmgr.h"
#include "utils/rel.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.
}
/*
- * Make unions of keys in IndexTuple vector, return FALSE if itvec contains
- * invalid tuple. Resulting Datums aren't compressed.
+ * Make unions of keys in IndexTuple vector (one union datum per index column).
+ * Union Datums are returned into the attr/isnull arrays.
+ * Resulting Datums aren't compressed.
*/
-
void
-gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startkey,
+gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
Datum *attr, bool *isnull)
{
int i;
evec = (GistEntryVector *) palloc((len + 2) * sizeof(GISTENTRY) + GEVHDRSZ);
- for (i = startkey; i < giststate->tupdesc->natts; i++)
+ for (i = 0; i < giststate->tupdesc->natts; i++)
{
int j;
+ /* Collect non-null datums for this column */
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;
evec->n++;
}
- /* If this tuple vector was all NULLs, the union is NULL */
+ /* If this column was all NULLs, the union is NULL */
if (evec->n == 0)
{
attr[i] = (Datum) 0;
{
if (evec->n == 1)
{
+ /* unionFn may expect at least two inputs */
evec->n = 2;
evec->vector[1] = evec->vector[0];
}
IndexTuple
gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
{
- memset(isnullS, TRUE, sizeof(bool) * giststate->tupdesc->natts);
+ Datum attr[INDEX_MAX_KEYS];
+ bool isnull[INDEX_MAX_KEYS];
- gistMakeUnionItVec(giststate, itvec, len, 0, attrS, isnullS);
+ gistMakeUnionItVec(giststate, itvec, len, attr, isnull);
- return gistFormTuple(giststate, r, attrS, isnullS, false);
+ return gistFormTuple(giststate, r, attr, isnull, false);
}
/*
GISTENTRY *entry2, bool isnull2,
Datum *dst, bool *dstisnull)
{
-
+ /* we need a GistEntryVector with room for exactly 2 elements */
+ union
+ {
+ GistEntryVector gev;
+ char padding[2 * sizeof(GISTENTRY) + GEVHDRSZ];
+ } storage;
+ GistEntryVector *evec = &storage.gev;
int dstsize;
- static char storage[2 * sizeof(GISTENTRY) + GEVHDRSZ];
- GistEntryVector *evec = (GistEntryVector *) storage;
-
evec->n = 2;
if (isnull1 && isnull2)
addentries[INDEX_MAX_KEYS];
bool oldisnull[INDEX_MAX_KEYS],
addisnull[INDEX_MAX_KEYS];
+ Datum attr[INDEX_MAX_KEYS];
+ bool isnull[INDEX_MAX_KEYS];
IndexTuple newtup = NULL;
int i;
gistMakeUnionKey(giststate, i,
oldentries + i, oldisnull[i],
addentries + i, addisnull[i],
- attrS + i, isnullS + i);
+ attr + i, isnull + i);
if (neednew)
/* we already need new key, so we can skip check */
continue;
- if (isnullS[i])
+ if (isnull[i])
/* union of key may be NULL if and only if both keys are NULL */
continue;
if (!addisnull[i])
{
- if (oldisnull[i] || gistKeyIsEQ(giststate, i, oldentries[i].key, attrS[i]) == false)
+ if (oldisnull[i] ||
+ !gistKeyIsEQ(giststate, i, oldentries[i].key, attr[i]))
neednew = true;
}
}
if (neednew)
{
/* need to update key */
- newtup = gistFormTuple(giststate, r, attrS, isnullS, false);
+ newtup = gistFormTuple(giststate, r, attr, isnull, false);
newtup->t_tid = oldtup->t_tid;
}
extern float gistpenalty(GISTSTATE *giststate, int attno,
GISTENTRY *key1, bool isNull1,
GISTENTRY *key2, bool isNull2);
-extern void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, int startkey,
+extern void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
Datum *attr, bool *isnull);
extern bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b);
extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,