mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
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.
This commit is contained in:
parent
785941cdc3
commit
55b59eda13
@ -89,11 +89,9 @@ gistbeginscan(PG_FUNCTION_ARGS)
|
|||||||
scan->opaque = so;
|
scan->opaque = so;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All fields required for index-only scans are null until gistrescan.
|
* All fields required for index-only scans are initialized in gistrescan,
|
||||||
* However, we set up scan->xs_itupdesc whether we'll need it or not,
|
* as we don't know yet if we're doing an index-only scan or not.
|
||||||
* since that's cheap.
|
|
||||||
*/
|
*/
|
||||||
scan->xs_itupdesc = RelationGetDescr(r);
|
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldCxt);
|
MemoryContextSwitchTo(oldCxt);
|
||||||
|
|
||||||
@ -149,15 +147,37 @@ gistrescan(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're doing an index-only scan, also create a memory context to hold
|
* If we're doing an index-only scan, on the first call, also initialize
|
||||||
* the returned tuples.
|
* a tuple descriptor to represent the returned index tuples and create a
|
||||||
|
* memory context to hold them during the scan.
|
||||||
*/
|
*/
|
||||||
if (scan->xs_want_itup && so->pageDataCxt == NULL)
|
if (scan->xs_want_itup && !scan->xs_itupdesc)
|
||||||
|
{
|
||||||
|
int natts;
|
||||||
|
int attno;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The storage type of the index can be different from the original
|
||||||
|
* datatype being indexed, so we cannot just grab the index's tuple
|
||||||
|
* descriptor. Instead, construct a descriptor with the original data
|
||||||
|
* types.
|
||||||
|
*/
|
||||||
|
natts = RelationGetNumberOfAttributes(scan->indexRelation);
|
||||||
|
so->giststate->fetchTupdesc = CreateTemplateTupleDesc(natts, false);
|
||||||
|
for (attno = 1; attno <= natts; attno++)
|
||||||
|
{
|
||||||
|
TupleDescInitEntry(so->giststate->fetchTupdesc, attno, NULL,
|
||||||
|
scan->indexRelation->rd_opcintype[attno - 1],
|
||||||
|
-1, 0);
|
||||||
|
}
|
||||||
|
scan->xs_itupdesc = so->giststate->fetchTupdesc;
|
||||||
|
|
||||||
so->pageDataCxt = AllocSetContextCreate(so->giststate->scanCxt,
|
so->pageDataCxt = AllocSetContextCreate(so->giststate->scanCxt,
|
||||||
"GiST page data context",
|
"GiST page data context",
|
||||||
ALLOCSET_DEFAULT_MINSIZE,
|
ALLOCSET_DEFAULT_MINSIZE,
|
||||||
ALLOCSET_DEFAULT_INITSIZE,
|
ALLOCSET_DEFAULT_INITSIZE,
|
||||||
ALLOCSET_DEFAULT_MAXSIZE);
|
ALLOCSET_DEFAULT_MAXSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
/* create new, empty RBTree for search queue */
|
/* create new, empty RBTree for search queue */
|
||||||
oldCxt = MemoryContextSwitchTo(so->queueCxt);
|
oldCxt = MemoryContextSwitchTo(so->queueCxt);
|
||||||
|
@ -657,7 +657,7 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
|
|||||||
}
|
}
|
||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
return index_form_tuple(giststate->tupdesc, fetchatt, isnull);
|
return index_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
|
@ -78,6 +78,8 @@ typedef struct GISTSTATE
|
|||||||
MemoryContext tempCxt; /* short-term context for calling functions */
|
MemoryContext tempCxt; /* short-term context for calling functions */
|
||||||
|
|
||||||
TupleDesc tupdesc; /* index's tuple descriptor */
|
TupleDesc tupdesc; /* index's tuple descriptor */
|
||||||
|
TupleDesc fetchTupdesc; /* tuple descriptor for tuples returned in an
|
||||||
|
* index-only scan */
|
||||||
|
|
||||||
FmgrInfo consistentFn[INDEX_MAX_KEYS];
|
FmgrInfo consistentFn[INDEX_MAX_KEYS];
|
||||||
FmgrInfo unionFn[INDEX_MAX_KEYS];
|
FmgrInfo unionFn[INDEX_MAX_KEYS];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user