aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gistutil.c
diff options
context:
space:
mode:
authorAlexander Korotkov <akorotkov@postgresql.org>2019-03-10 11:36:47 +0300
committerAlexander Korotkov <akorotkov@postgresql.org>2019-03-10 11:37:17 +0300
commitf2e403803fe6deb8cff59ea09dff42c6163b2110 (patch)
tree1c3afef6e11f6498002b88219d9644e71bb5972d /src/backend/access/gist/gistutil.c
parenta0b762626884b3b949c2703abb1c4b42fbbdfdc6 (diff)
downloadpostgresql-f2e403803fe6deb8cff59ea09dff42c6163b2110.tar.gz
postgresql-f2e403803fe6deb8cff59ea09dff42c6163b2110.zip
Support for INCLUDE attributes in GiST indexes
Similarly to B-tree, GiST index access method gets support of INCLUDE attributes. These attributes aren't used for tree navigation and aren't present in non-leaf pages. But they are present in leaf pages and can be fetched during index-only scan. The point of having INCLUDE attributes in GiST indexes is slightly different from the point of having them in B-tree. The main point of INCLUDE attributes in B-tree is to define UNIQUE constraint over part of attributes enabled for index-only scan. In GiST the main point of INCLUDE attributes is to use index-only scan for attributes, whose data types don't have GiST opclasses. Discussion: https://postgr.es/m/73A1A452-AD5F-40D4-BD61-978622FF75C1%40yandex-team.ru Author: Andrey Borodin, with small changes by me Reviewed-by: Andreas Karlsson
Diffstat (limited to 'src/backend/access/gist/gistutil.c')
-rw-r--r--src/backend/access/gist/gistutil.c53
1 files changed, 40 insertions, 13 deletions
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 8d3dfad27bd..f32e16eed58 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -160,7 +160,7 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
evec = (GistEntryVector *) palloc((len + 2) * sizeof(GISTENTRY) + GEVHDRSZ);
- for (i = 0; i < giststate->tupdesc->natts; i++)
+ for (i = 0; i < giststate->nonLeafTupdesc->natts; i++)
{
int j;
@@ -171,7 +171,8 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
Datum datum;
bool IsNull;
- datum = index_getattr(itvec[j], i + 1, giststate->tupdesc, &IsNull);
+ datum = index_getattr(itvec[j], i + 1, giststate->leafTupdesc,
+ &IsNull);
if (IsNull)
continue;
@@ -296,11 +297,11 @@ gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,
{
int i;
- for (i = 0; i < r->rd_att->natts; i++)
+ for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
{
Datum datum;
- datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);
+ datum = index_getattr(tuple, i + 1, giststate->leafTupdesc, &isnull[i]);
gistdentryinit(giststate, i, &attdata[i],
datum, r, p, o,
false, isnull[i]);
@@ -329,7 +330,7 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
gistDeCompressAtt(giststate, r, addtup, NULL,
(OffsetNumber) 0, addentries, addisnull);
- for (i = 0; i < r->rd_att->natts; i++)
+ for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
{
gistMakeUnionKey(giststate, i,
oldentries + i, oldisnull[i],
@@ -442,14 +443,15 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
zero_penalty = true;
/* Loop over index attributes. */
- for (j = 0; j < r->rd_att->natts; j++)
+ for (j = 0; j < IndexRelationGetNumberOfKeyAttributes(r); j++)
{
Datum datum;
float usize;
bool IsNull;
/* Compute penalty for this column. */
- datum = index_getattr(itup, j + 1, giststate->tupdesc, &IsNull);
+ datum = index_getattr(itup, j + 1, giststate->leafTupdesc,
+ &IsNull);
gistdentryinit(giststate, j, &entry, datum, r, p, i,
false, IsNull);
usize = gistpenalty(giststate, j, &entry, IsNull,
@@ -470,7 +472,7 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
result = i;
best_penalty[j] = usize;
- if (j < r->rd_att->natts - 1)
+ if (j < IndexRelationGetNumberOfKeyAttributes(r) - 1)
best_penalty[j + 1] = -1;
/* we have new best, so reset keep-it decision */
@@ -500,7 +502,7 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
* If we looped past the last column, and did not update "result",
* then this tuple is exactly as good as the prior best tuple.
*/
- if (j == r->rd_att->natts && result != i)
+ if (j == IndexRelationGetNumberOfKeyAttributes(r) && result != i)
{
if (keep_current_best == -1)
{
@@ -579,7 +581,7 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
/*
* Call the compress method on each attribute.
*/
- for (i = 0; i < r->rd_att->natts; i++)
+ for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
{
if (isnull[i])
compatt[i] = (Datum) 0;
@@ -602,7 +604,23 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
}
}
- res = index_form_tuple(giststate->tupdesc, compatt, isnull);
+ if (isleaf)
+ {
+ /*
+ * Emplace each included attribute if any.
+ */
+ for (; i < r->rd_att->natts; i++)
+ {
+ if (isnull[i])
+ compatt[i] = (Datum) 0;
+ else
+ compatt[i] = attdata[i];
+ }
+ }
+
+ res = index_form_tuple(isleaf ? giststate->leafTupdesc :
+ giststate->nonLeafTupdesc,
+ compatt, isnull);
/*
* The offset number on tuples on internal pages is unused. For historical
@@ -644,11 +662,11 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
bool isnull[INDEX_MAX_KEYS];
int i;
- for (i = 0; i < r->rd_att->natts; i++)
+ for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
{
Datum datum;
- datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);
+ datum = index_getattr(tuple, i + 1, giststate->leafTupdesc, &isnull[i]);
if (giststate->fetchFn[i].fn_oid != InvalidOid)
{
@@ -679,6 +697,15 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
fetchatt[i] = (Datum) 0;
}
}
+
+ /*
+ * Get each included attribute.
+ */
+ for (; i < r->rd_att->natts; i++)
+ {
+ fetchatt[i] = index_getattr(tuple, i + 1, giststate->leafTupdesc,
+ &isnull[i]);
+ }
MemoryContextSwitchTo(oldcxt);
return heap_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);