aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeIndexonlyscan.c
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/executor/nodeIndexonlyscan.c
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/executor/nodeIndexonlyscan.c')
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 66c2ad66d71..4a7f39a7c7d 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -149,9 +149,26 @@ IndexOnlyNext(IndexOnlyScanState *node)
}
/*
- * Fill the scan tuple slot with data from the index.
+ * Fill the scan tuple slot with data from the index. This might be
+ * provided in either HeapTuple or IndexTuple format. Conceivably an
+ * index AM might fill both fields, in which case we prefer the heap
+ * format, since it's probably a bit cheaper to fill a slot from.
*/
- StoreIndexTuple(slot, scandesc->xs_itup, scandesc->xs_itupdesc);
+ if (scandesc->xs_hitup)
+ {
+ /*
+ * We don't take the trouble to verify that the provided tuple has
+ * exactly the slot's format, but it seems worth doing a quick
+ * check on the number of fields.
+ */
+ Assert(slot->tts_tupleDescriptor->natts ==
+ scandesc->xs_hitupdesc->natts);
+ ExecStoreTuple(scandesc->xs_hitup, slot, InvalidBuffer, false);
+ }
+ else if (scandesc->xs_itup)
+ StoreIndexTuple(slot, scandesc->xs_itup, scandesc->xs_itupdesc);
+ else
+ elog(ERROR, "no data returned for index-only scan");
/*
* If the index was lossy, we have to recheck the index quals.