mirror of
https://github.com/postgres/postgres.git
synced 2025-08-22 21:53:06 +03:00
Add support for index-only scans in GiST.
This adds a new GiST opclass method, 'fetch', which is used to reconstruct the original Datum from the value stored in the index. Also, the 'canreturn' index AM interface function gains a new 'attno' argument. That makes it possible to use index-only scans on a multi-column index where some of the opclasses support index-only scans but some do not. This patch adds support in the box and point opclasses. Other opclasses can added later as follow-on patches (btree_gist would be particularly interesting). Anastasia Lubennikova, with additional fixes and modifications by me.
This commit is contained in:
@@ -294,8 +294,9 @@ gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,
|
||||
|
||||
for (i = 0; i < r->rd_att->natts; i++)
|
||||
{
|
||||
Datum datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);
|
||||
Datum datum;
|
||||
|
||||
datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);
|
||||
gistdentryinit(giststate, i, &attdata[i],
|
||||
datum, r, p, o,
|
||||
FALSE, isnull[i]);
|
||||
@@ -598,6 +599,67 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize a GiST entry with fetched value in key field
|
||||
*/
|
||||
static Datum
|
||||
gistFetchAtt(GISTSTATE *giststate, int nkey, Datum k, Relation r)
|
||||
{
|
||||
GISTENTRY fentry;
|
||||
GISTENTRY *fep;
|
||||
|
||||
gistentryinit(fentry, k, r, NULL, (OffsetNumber) 0, false);
|
||||
|
||||
fep = (GISTENTRY *)
|
||||
DatumGetPointer(FunctionCall1Coll(&giststate->fetchFn[nkey],
|
||||
giststate->supportCollation[nkey],
|
||||
PointerGetDatum(&fentry)));
|
||||
|
||||
/* fetchFn set 'key', return it to the caller */
|
||||
return fep->key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch all keys in tuple.
|
||||
* returns new IndexTuple that contains GISTENTRY with fetched data
|
||||
*/
|
||||
IndexTuple
|
||||
gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
|
||||
{
|
||||
MemoryContext oldcxt = MemoryContextSwitchTo(giststate->tempCxt);
|
||||
Datum fetchatt[INDEX_MAX_KEYS];
|
||||
bool isnull[INDEX_MAX_KEYS];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < r->rd_att->natts; i++)
|
||||
{
|
||||
Datum datum;
|
||||
|
||||
datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);
|
||||
|
||||
if (giststate->fetchFn[i].fn_oid != InvalidOid)
|
||||
{
|
||||
if (!isnull[i])
|
||||
fetchatt[i] = gistFetchAtt(giststate, i, datum, r);
|
||||
else
|
||||
fetchatt[i] = (Datum) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Index-only scans not supported for this column. Since the
|
||||
* planner chose an index-only scan anyway, it is not interested
|
||||
* in this column, and we can replace it with a NULL.
|
||||
*/
|
||||
isnull[i] = true;
|
||||
fetchatt[i] = (Datum) 0;
|
||||
}
|
||||
}
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
|
||||
return index_form_tuple(giststate->tupdesc, fetchatt, isnull);
|
||||
}
|
||||
|
||||
float
|
||||
gistpenalty(GISTSTATE *giststate, int attno,
|
||||
GISTENTRY *orig, bool isNullOrig,
|
||||
|
Reference in New Issue
Block a user