Skip to content

Commit 55b59ed

Browse files
committed
Fix GiST index-only scans for opclasses with different storage type.
We cannot use the index's tuple descriptor directly to describe the index tuples returned in an index-only scan. That's because the index might use a different datatype for the values stored on disk than the type originally indexed. As long as they were both pass-by-ref, it worked, but will not work for pass-by-value types of different sizes. I noticed this as a crash when I started hacking a patch to add fetch methods to btree_gist.
1 parent 785941c commit 55b59ed

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

src/backend/access/gist/gistscan.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,9 @@ gistbeginscan(PG_FUNCTION_ARGS)
8989
scan->opaque = so;
9090

9191
/*
92-
* All fields required for index-only scans are null until gistrescan.
93-
* However, we set up scan->xs_itupdesc whether we'll need it or not,
94-
* since that's cheap.
92+
* All fields required for index-only scans are initialized in gistrescan,
93+
* as we don't know yet if we're doing an index-only scan or not.
9594
*/
96-
scan->xs_itupdesc = RelationGetDescr(r);
9795

9896
MemoryContextSwitchTo(oldCxt);
9997

@@ -149,15 +147,37 @@ gistrescan(PG_FUNCTION_ARGS)
149147
}
150148

151149
/*
152-
* If we're doing an index-only scan, also create a memory context to hold
153-
* the returned tuples.
150+
* If we're doing an index-only scan, on the first call, also initialize
151+
* a tuple descriptor to represent the returned index tuples and create a
152+
* memory context to hold them during the scan.
154153
*/
155-
if (scan->xs_want_itup && so->pageDataCxt == NULL)
154+
if (scan->xs_want_itup && !scan->xs_itupdesc)
155+
{
156+
int natts;
157+
int attno;
158+
159+
/*
160+
* The storage type of the index can be different from the original
161+
* datatype being indexed, so we cannot just grab the index's tuple
162+
* descriptor. Instead, construct a descriptor with the original data
163+
* types.
164+
*/
165+
natts = RelationGetNumberOfAttributes(scan->indexRelation);
166+
so->giststate->fetchTupdesc = CreateTemplateTupleDesc(natts, false);
167+
for (attno = 1; attno <= natts; attno++)
168+
{
169+
TupleDescInitEntry(so->giststate->fetchTupdesc, attno, NULL,
170+
scan->indexRelation->rd_opcintype[attno - 1],
171+
-1, 0);
172+
}
173+
scan->xs_itupdesc = so->giststate->fetchTupdesc;
174+
156175
so->pageDataCxt = AllocSetContextCreate(so->giststate->scanCxt,
157176
"GiST page data context",
158177
ALLOCSET_DEFAULT_MINSIZE,
159178
ALLOCSET_DEFAULT_INITSIZE,
160179
ALLOCSET_DEFAULT_MAXSIZE);
180+
}
161181

162182
/* create new, empty RBTree for search queue */
163183
oldCxt = MemoryContextSwitchTo(so->queueCxt);

src/backend/access/gist/gistutil.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
657657
}
658658
MemoryContextSwitchTo(oldcxt);
659659

660-
return index_form_tuple(giststate->tupdesc, fetchatt, isnull);
660+
return index_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);
661661
}
662662

663663
float

src/include/access/gist_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ typedef struct GISTSTATE
7878
MemoryContext tempCxt; /* short-term context for calling functions */
7979

8080
TupleDesc tupdesc; /* index's tuple descriptor */
81+
TupleDesc fetchTupdesc; /* tuple descriptor for tuples returned in an
82+
* index-only scan */
8183

8284
FmgrInfo consistentFn[INDEX_MAX_KEYS];
8385
FmgrInfo unionFn[INDEX_MAX_KEYS];

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy