mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
Allow index AMs to return either HeapTuple or IndexTuple format during IOS.
Previously, only IndexTuple format was supported for the output data of an index-only scan. This is fine for btree, which is just returning a verbatim index tuple anyway. It's not so fine for SP-GiST, which can return reconstructed data that's much larger than a page. To fix, extend the index AM API so that index-only scan data can be returned in either HeapTuple or IndexTuple format. There's other ways we could have done it, but this way avoids an API break for index AMs that aren't concerned with the issue, and it costs little except a couple more fields in IndexScanDescs. I changed both GiST and SP-GiST to use the HeapTuple method. I'm not very clear on whether GiST can reconstruct data that's too large for an IndexTuple, but that seems possible, and it's not much of a code change to fix. Per a complaint from Vik Fearing. Reviewed by Jason Li. Discussion: https://postgr.es/m/49527f79-530d-0bfe-3dad-d183596afa92@2ndquadrant.fr
This commit is contained in:
@ -441,12 +441,13 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
|
||||
so->pageData[so->nPageData].offnum = i;
|
||||
|
||||
/*
|
||||
* In an index-only scan, also fetch the data from the tuple.
|
||||
* In an index-only scan, also fetch the data from the tuple. The
|
||||
* reconstructed tuples are stored in pageDataCxt.
|
||||
*/
|
||||
if (scan->xs_want_itup)
|
||||
{
|
||||
oldcxt = MemoryContextSwitchTo(so->pageDataCxt);
|
||||
so->pageData[so->nPageData].ftup =
|
||||
so->pageData[so->nPageData].recontup =
|
||||
gistFetchTuple(giststate, r, it);
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
}
|
||||
@ -478,7 +479,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
|
||||
* In an index-only scan, also fetch the data from the tuple.
|
||||
*/
|
||||
if (scan->xs_want_itup)
|
||||
item->data.heap.ftup = gistFetchTuple(giststate, r, it);
|
||||
item->data.heap.recontup = gistFetchTuple(giststate, r, it);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -540,11 +541,11 @@ getNextNearest(IndexScanDesc scan)
|
||||
bool res = false;
|
||||
int i;
|
||||
|
||||
if (scan->xs_itup)
|
||||
if (scan->xs_hitup)
|
||||
{
|
||||
/* free previously returned tuple */
|
||||
pfree(scan->xs_itup);
|
||||
scan->xs_itup = NULL;
|
||||
pfree(scan->xs_hitup);
|
||||
scan->xs_hitup = NULL;
|
||||
}
|
||||
|
||||
do
|
||||
@ -601,7 +602,7 @@ getNextNearest(IndexScanDesc scan)
|
||||
|
||||
/* in an index-only scan, also return the reconstructed tuple. */
|
||||
if (scan->xs_want_itup)
|
||||
scan->xs_itup = item->data.heap.ftup;
|
||||
scan->xs_hitup = item->data.heap.recontup;
|
||||
res = true;
|
||||
}
|
||||
else
|
||||
@ -685,7 +686,7 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
|
||||
|
||||
/* in an index-only scan, also return the reconstructed tuple */
|
||||
if (scan->xs_want_itup)
|
||||
scan->xs_itup = so->pageData[so->curPageData].ftup;
|
||||
scan->xs_hitup = so->pageData[so->curPageData].recontup;
|
||||
|
||||
so->curPageData++;
|
||||
|
||||
|
@ -155,7 +155,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
|
||||
* tuple descriptor to represent the returned index tuples and create a
|
||||
* memory context to hold them during the scan.
|
||||
*/
|
||||
if (scan->xs_want_itup && !scan->xs_itupdesc)
|
||||
if (scan->xs_want_itup && !scan->xs_hitupdesc)
|
||||
{
|
||||
int natts;
|
||||
int attno;
|
||||
@ -174,8 +174,9 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
|
||||
scan->indexRelation->rd_opcintype[attno - 1],
|
||||
-1, 0);
|
||||
}
|
||||
scan->xs_itupdesc = so->giststate->fetchTupdesc;
|
||||
scan->xs_hitupdesc = so->giststate->fetchTupdesc;
|
||||
|
||||
/* Also create a memory context that will hold the returned tuples */
|
||||
so->pageDataCxt = AllocSetContextCreate(so->giststate->scanCxt,
|
||||
"GiST page data context",
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
|
@ -624,9 +624,9 @@ gistFetchAtt(GISTSTATE *giststate, int nkey, Datum k, Relation r)
|
||||
|
||||
/*
|
||||
* Fetch all keys in tuple.
|
||||
* returns new IndexTuple that contains GISTENTRY with fetched data
|
||||
* Returns a new HeapTuple containing the originally-indexed data.
|
||||
*/
|
||||
IndexTuple
|
||||
HeapTuple
|
||||
gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
|
||||
{
|
||||
MemoryContext oldcxt = MemoryContextSwitchTo(giststate->tempCxt);
|
||||
@ -660,7 +660,7 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
|
||||
}
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
|
||||
return index_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);
|
||||
return heap_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);
|
||||
}
|
||||
|
||||
float
|
||||
|
Reference in New Issue
Block a user