1
0
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:
Heikki Linnakangas
2015-03-26 19:12:00 +02:00
parent 8fa393a6d7
commit d04c8ed904
24 changed files with 575 additions and 73 deletions

View File

@@ -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,