aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-02-27 17:20:34 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2017-02-27 17:20:34 -0500
commit9b88f27cb42fe8ff59ddc75e29c005624b8850a2 (patch)
tree285c2882206b72c19cc9ac5f7e84a33b663e204c /src/backend/access
parent30df93f698d016d086e8961aa6c6076b37ea0ef4 (diff)
downloadpostgresql-9b88f27cb42fe8ff59ddc75e29c005624b8850a2.tar.gz
postgresql-9b88f27cb42fe8ff59ddc75e29c005624b8850a2.zip
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
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/gist/gistget.c17
-rw-r--r--src/backend/access/gist/gistscan.c5
-rw-r--r--src/backend/access/gist/gistutil.c6
-rw-r--r--src/backend/access/index/genam.c2
-rw-r--r--src/backend/access/index/indexam.c4
-rw-r--r--src/backend/access/spgist/spgscan.c24
6 files changed, 31 insertions, 27 deletions
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index eea366b1ad4..122dc38db56 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -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++;
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 33b388906aa..81ff8fc8b6e 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -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);
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index f92baedffdd..75845ba0e76 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -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
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index c4a393f34e8..35994769307 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -119,6 +119,8 @@ RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
scan->xs_itup = NULL;
scan->xs_itupdesc = NULL;
+ scan->xs_hitup = NULL;
+ scan->xs_hitupdesc = NULL;
ItemPointerSetInvalid(&scan->xs_ctup.t_self);
scan->xs_ctup.t_data = NULL;
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 4e7eca73cce..cc5ac8b8571 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -535,8 +535,8 @@ index_getnext_tid(IndexScanDesc scan, ScanDirection direction)
/*
* The AM's amgettuple proc finds the next index entry matching the scan
* keys, and puts the TID into scan->xs_ctup.t_self. It should also set
- * scan->xs_recheck and possibly scan->xs_itup, though we pay no attention
- * to those fields here.
+ * scan->xs_recheck and possibly scan->xs_itup/scan->xs_hitup, though we
+ * pay no attention to those fields here.
*/
found = scan->indexRelation->rd_amroutine->amgettuple(scan, direction);
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index 139d9986004..2d96c0094e6 100644
--- a/src/backend/access/spgist/spgscan.c
+++ b/src/backend/access/spgist/spgscan.c
@@ -92,11 +92,11 @@ resetSpGistScanOpaque(SpGistScanOpaque so)
if (so->want_itup)
{
- /* Must pfree IndexTuples to avoid memory leak */
+ /* Must pfree reconstructed tuples to avoid memory leak */
int i;
for (i = 0; i < so->nPtrs; i++)
- pfree(so->indexTups[i]);
+ pfree(so->reconTups[i]);
}
so->iPtr = so->nPtrs = 0;
}
@@ -195,8 +195,8 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
"SP-GiST search temporary context",
ALLOCSET_DEFAULT_SIZES);
- /* Set up indexTupDesc and xs_itupdesc in case it's an index-only scan */
- so->indexTupDesc = scan->xs_itupdesc = RelationGetDescr(rel);
+ /* Set up indexTupDesc and xs_hitupdesc in case it's an index-only scan */
+ so->indexTupDesc = scan->xs_hitupdesc = RelationGetDescr(rel);
scan->opaque = so;
@@ -591,12 +591,12 @@ storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr,
if (so->want_itup)
{
/*
- * Reconstruct desired IndexTuple. We have to copy the datum out of
- * the temp context anyway, so we may as well create the tuple here.
+ * Reconstruct index data. We have to copy the datum out of the temp
+ * context anyway, so we may as well create the tuple here.
*/
- so->indexTups[so->nPtrs] = index_form_tuple(so->indexTupDesc,
- &leafValue,
- &isnull);
+ so->reconTups[so->nPtrs] = heap_form_tuple(so->indexTupDesc,
+ &leafValue,
+ &isnull);
}
so->nPtrs++;
}
@@ -619,18 +619,18 @@ spggettuple(IndexScanDesc scan, ScanDirection dir)
/* continuing to return tuples from a leaf page */
scan->xs_ctup.t_self = so->heapPtrs[so->iPtr];
scan->xs_recheck = so->recheck[so->iPtr];
- scan->xs_itup = so->indexTups[so->iPtr];
+ scan->xs_hitup = so->reconTups[so->iPtr];
so->iPtr++;
return true;
}
if (so->want_itup)
{
- /* Must pfree IndexTuples to avoid memory leak */
+ /* Must pfree reconstructed tuples to avoid memory leak */
int i;
for (i = 0; i < so->nPtrs; i++)
- pfree(so->indexTups[i]);
+ pfree(so->reconTups[i]);
}
so->iPtr = so->nPtrs = 0;