From 79b379ca574da7d18f5b867656caac5cba7fb696 Mon Sep 17 00:00:00 2001 From: Hari Babu Date: Thu, 29 Mar 2018 16:59:20 +1100 Subject: [PATCH 07/16] Scan functions are added to table AM Replaced HeapTuple with StorageTuple wherever possible. Currently directly returning slot functionality instead of tuple is added only to limited number of places. --- contrib/amcheck/verify_nbtree.c | 2 +- contrib/pgrowlocks/pgrowlocks.c | 6 +- contrib/pgstattuple/pgstattuple.c | 6 +- src/backend/access/heap/heapam.c | 223 ++++++++++----------------- src/backend/access/heap/heapam_handler.c | 9 ++ src/backend/access/index/genam.c | 11 +- src/backend/access/index/indexam.c | 13 +- src/backend/access/nbtree/nbtinsert.c | 7 +- src/backend/access/nbtree/nbtsort.c | 2 +- src/backend/access/table/tableam.c | 233 +++++++++++++++++++++++++++++ src/backend/bootstrap/bootstrap.c | 25 ++-- src/backend/catalog/aclchk.c | 13 +- src/backend/catalog/index.c | 49 +++--- src/backend/catalog/partition.c | 1 + src/backend/catalog/pg_conversion.c | 7 +- src/backend/catalog/pg_db_role_setting.c | 7 +- src/backend/catalog/pg_publication.c | 7 +- src/backend/catalog/pg_subscription.c | 7 +- src/backend/commands/cluster.c | 12 +- src/backend/commands/constraint.c | 3 +- src/backend/commands/copy.c | 6 +- src/backend/commands/dbcommands.c | 19 +-- src/backend/commands/indexcmds.c | 7 +- src/backend/commands/tablecmds.c | 30 ++-- src/backend/commands/tablespace.c | 39 ++--- src/backend/commands/typecmds.c | 13 +- src/backend/commands/vacuum.c | 13 +- src/backend/executor/execAmi.c | 2 +- src/backend/executor/execIndexing.c | 13 +- src/backend/executor/execReplication.c | 15 +- src/backend/executor/execTuples.c | 8 +- src/backend/executor/functions.c | 4 +- src/backend/executor/nodeAgg.c | 4 +- src/backend/executor/nodeBitmapHeapscan.c | 19 +-- src/backend/executor/nodeForeignscan.c | 6 +- src/backend/executor/nodeGather.c | 8 +- src/backend/executor/nodeGatherMerge.c | 14 +- src/backend/executor/nodeIndexonlyscan.c | 8 +- src/backend/executor/nodeIndexscan.c | 16 +- src/backend/executor/nodeSamplescan.c | 34 +++-- src/backend/executor/nodeSeqscan.c | 45 ++---- src/backend/executor/nodeWindowAgg.c | 4 +- src/backend/executor/spi.c | 20 +-- src/backend/executor/tqueue.c | 2 +- src/backend/partitioning/partbounds.c | 7 +- src/backend/postmaster/autovacuum.c | 18 +-- src/backend/postmaster/pgstat.c | 7 +- src/backend/replication/logical/launcher.c | 7 +- src/backend/rewrite/rewriteDefine.c | 7 +- src/backend/utils/init/postinit.c | 7 +- src/include/access/heapam.h | 27 ++-- src/include/access/tableam.h | 35 +++++ src/include/access/tableam_common.h | 1 + src/include/access/tableamapi.h | 44 ++++++ src/include/executor/functions.h | 2 +- src/include/executor/spi.h | 12 +- src/include/executor/tqueue.h | 4 +- src/include/funcapi.h | 2 +- 58 files changed, 719 insertions(+), 453 deletions(-) diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index 075e5548b9..70dbdcbd30 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -497,7 +497,7 @@ bt_check_every_level(Relation rel, Relation heaprel, bool readonly, * * Note that IndexBuildHeapScan() calls heap_endscan() for us. */ - scan = heap_beginscan_strat(state->heaprel, /* relation */ + scan = table_beginscan_strat(state->heaprel, /* relation */ snapshot, /* snapshot */ 0, /* number of keys */ NULL, /* scan key */ diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c index b0ed27e883..6d47a446ea 100644 --- a/contrib/pgrowlocks/pgrowlocks.c +++ b/contrib/pgrowlocks/pgrowlocks.c @@ -125,7 +125,7 @@ pgrowlocks(PG_FUNCTION_ARGS) aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind), RelationGetRelationName(rel)); - scan = heap_beginscan(rel, GetActiveSnapshot(), 0, NULL); + scan = table_beginscan(rel, GetActiveSnapshot(), 0, NULL); mydata = palloc(sizeof(*mydata)); mydata->rel = rel; mydata->scan = scan; @@ -141,7 +141,7 @@ pgrowlocks(PG_FUNCTION_ARGS) scan = mydata->scan; /* scan the relation */ - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { HTSU_Result htsu; TransactionId xmax; @@ -306,7 +306,7 @@ pgrowlocks(PG_FUNCTION_ARGS) } } - heap_endscan(scan); + table_endscan(scan); heap_close(mydata->rel, AccessShareLock); SRF_RETURN_DONE(funcctx); diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 03f67c0beb..d9b08796c8 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -328,13 +328,13 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) TableAmRoutine *method = rel->rd_tableamroutine; /* Disable syncscan because we assume we scan from block zero upwards */ - scan = heap_beginscan_strat(rel, SnapshotAny, 0, NULL, true, false); + scan = table_beginscan_strat(rel, SnapshotAny, 0, NULL, true, false); InitDirtySnapshot(SnapshotDirty); nblocks = scan->rs_nblocks; /* # blocks to be scanned */ /* scan the relation */ - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { CHECK_FOR_INTERRUPTS(); @@ -387,7 +387,7 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) block++; } - heap_endscan(scan); + table_endscan(scan); relation_close(rel, AccessShareLock); stat.table_len = (uint64) nblocks * BLCKSZ; diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 67b9b07337..c8fee6a4cb 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -83,17 +83,6 @@ /* GUC variable */ bool synchronize_seqscans = true; - -static HeapScanDesc heap_beginscan_internal(Relation relation, - Snapshot snapshot, - int nkeys, ScanKey key, - ParallelHeapScanDesc parallel_scan, - bool allow_strat, - bool allow_sync, - bool allow_pagemode, - bool is_bitmapscan, - bool is_samplescan, - bool temp_snap); static void heap_parallelscan_startblock_init(HeapScanDesc scan); static BlockNumber heap_parallelscan_nextpage(HeapScanDesc scan); static HeapTuple heap_prepare_insert(Relation relation, HeapTuple tup, @@ -1394,87 +1383,16 @@ heap_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, return r; } - -/* ---------------- - * heap_beginscan - begin relation scan - * - * heap_beginscan is the "standard" case. - * - * heap_beginscan_catalog differs in setting up its own temporary snapshot. - * - * heap_beginscan_strat offers an extended API that lets the caller control - * whether a nondefault buffer access strategy can be used, and whether - * syncscan can be chosen (possibly resulting in the scan not starting from - * block zero). Both of these default to true with plain heap_beginscan. - * - * heap_beginscan_bm is an alternative entry point for setting up a - * HeapScanDesc for a bitmap heap scan. Although that scan technology is - * really quite unlike a standard seqscan, there is just enough commonality - * to make it worth using the same data structure. - * - * heap_beginscan_sampling is an alternative entry point for setting up a - * HeapScanDesc for a TABLESAMPLE scan. As with bitmap scans, it's worth - * using the same data structure although the behavior is rather different. - * In addition to the options offered by heap_beginscan_strat, this call - * also allows control of whether page-mode visibility checking is used. - * ---------------- - */ HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot, - int nkeys, ScanKey key) -{ - return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL, - true, true, true, false, false, false); -} - -HeapScanDesc -heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key) -{ - Oid relid = RelationGetRelid(relation); - Snapshot snapshot = RegisterSnapshot(GetCatalogSnapshot(relid)); - - return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL, - true, true, true, false, false, true); -} - -HeapScanDesc -heap_beginscan_strat(Relation relation, Snapshot snapshot, - int nkeys, ScanKey key, - bool allow_strat, bool allow_sync) -{ - return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL, - allow_strat, allow_sync, true, - false, false, false); -} - -HeapScanDesc -heap_beginscan_bm(Relation relation, Snapshot snapshot, - int nkeys, ScanKey key) -{ - return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL, - false, false, true, true, false, false); -} - -HeapScanDesc -heap_beginscan_sampling(Relation relation, Snapshot snapshot, - int nkeys, ScanKey key, - bool allow_strat, bool allow_sync, bool allow_pagemode) -{ - return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL, - allow_strat, allow_sync, allow_pagemode, - false, true, false); -} - -static HeapScanDesc -heap_beginscan_internal(Relation relation, Snapshot snapshot, - int nkeys, ScanKey key, - ParallelHeapScanDesc parallel_scan, - bool allow_strat, - bool allow_sync, - bool allow_pagemode, - bool is_bitmapscan, - bool is_samplescan, - bool temp_snap) + int nkeys, ScanKey key, + ParallelHeapScanDesc parallel_scan, + bool allow_strat, + bool allow_sync, + bool allow_pagemode, + bool is_bitmapscan, + bool is_samplescan, + bool temp_snap) { HeapScanDesc scan; @@ -1544,9 +1462,16 @@ heap_beginscan_internal(Relation relation, Snapshot snapshot, * ---------------- */ void -heap_rescan(HeapScanDesc scan, - ScanKey key) +heap_rescan(HeapScanDesc scan, ScanKey key, bool set_params, + bool allow_strat, bool allow_sync, bool allow_pagemode) { + if (set_params) + { + scan->rs_allow_strat = allow_strat; + scan->rs_allow_sync = allow_sync; + scan->rs_pageatatime = allow_pagemode && IsMVCCSnapshot(scan->rs_snapshot); + } + /* * unpin scan buffers */ @@ -1557,27 +1482,21 @@ heap_rescan(HeapScanDesc scan, * reinitialize scan descriptor */ initscan(scan, key, true); -} -/* ---------------- - * heap_rescan_set_params - restart a relation scan after changing params - * - * This call allows changing the buffer strategy, syncscan, and pagemode - * options before starting a fresh scan. Note that although the actual use - * of syncscan might change (effectively, enabling or disabling reporting), - * the previously selected startblock will be kept. - * ---------------- - */ -void -heap_rescan_set_params(HeapScanDesc scan, ScanKey key, - bool allow_strat, bool allow_sync, bool allow_pagemode) -{ - /* adjust parameters */ - scan->rs_allow_strat = allow_strat; - scan->rs_allow_sync = allow_sync; - scan->rs_pageatatime = allow_pagemode && IsMVCCSnapshot(scan->rs_snapshot); - /* ... and rescan */ - heap_rescan(scan, key); + /* + * reset parallel scan, if present + */ + if (scan->rs_parallel != NULL) + { + ParallelHeapScanDesc parallel_scan; + + /* + * Caller is responsible for making sure that all workers have + * finished the scan before calling this. + */ + parallel_scan = scan->rs_parallel; + pg_atomic_write_u64(¶llel_scan->phs_nallocated, 0); + } } /* ---------------- @@ -1675,36 +1594,6 @@ heap_parallelscan_reinitialize(ParallelHeapScanDesc parallel_scan) pg_atomic_write_u64(¶llel_scan->phs_nallocated, 0); } -/* ---------------- - * heap_beginscan_parallel - join a parallel scan - * - * Caller must hold a suitable lock on the correct relation. - * ---------------- - */ -HeapScanDesc -heap_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan) -{ - Snapshot snapshot; - - Assert(RelationGetRelid(relation) == parallel_scan->phs_relid); - - if (!parallel_scan->phs_snapshot_any) - { - /* Snapshot was serialized -- restore it */ - snapshot = RestoreSnapshot(parallel_scan->phs_snapshot_data); - RegisterSnapshot(snapshot); - } - else - { - /* SnapshotAny passed by caller (not serialized) */ - snapshot = SnapshotAny; - } - - return heap_beginscan_internal(relation, snapshot, 0, NULL, parallel_scan, - true, true, true, false, false, - !parallel_scan->phs_snapshot_any); -} - /* ---------------- * heap_parallelscan_startblock_init - find and set the scan's startblock * @@ -1849,8 +1738,7 @@ heap_update_snapshot(HeapScanDesc scan, Snapshot snapshot) #define HEAPDEBUG_3 #endif /* !defined(HEAPDEBUGALL) */ - -HeapTuple +TableTuple heap_getnext(HeapScanDesc scan, ScanDirection direction) { /* Note: no locking manipulations needed */ @@ -1880,6 +1768,53 @@ heap_getnext(HeapScanDesc scan, ScanDirection direction) return heap_copytuple(&(scan->rs_ctup)); } +#ifdef HEAPAMSLOTDEBUGALL +#define HEAPAMSLOTDEBUG_1 \ + elog(DEBUG2, "heapam_getnext([%s,nkeys=%d],dir=%d) called", \ + RelationGetRelationName(scan->rs_rd), scan->rs_nkeys, (int) direction) +#define HEAPAMSLOTDEBUG_2 \ + elog(DEBUG2, "heapam_getnext returning EOS") +#define HEAPAMSLOTDEBUG_3 \ + elog(DEBUG2, "heapam_getnext returning tuple") +#else +#define HEAPAMSLOTDEBUG_1 +#define HEAPAMSLOTDEBUG_2 +#define HEAPAMSLOTDEBUG_3 +#endif + +TupleTableSlot * +heap_getnextslot(HeapScanDesc sscan, ScanDirection direction, TupleTableSlot *slot) +{ + HeapScanDesc scan = (HeapScanDesc) sscan; + + /* Note: no locking manipulations needed */ + + HEAPAMSLOTDEBUG_1; /* heap_getnext( info ) */ + + if (scan->rs_pageatatime) + heapgettup_pagemode(scan, direction, + scan->rs_nkeys, scan->rs_key); + else + heapgettup(scan, direction, scan->rs_nkeys, scan->rs_key); + + if (scan->rs_ctup.t_data == NULL) + { + HEAPAMSLOTDEBUG_2; /* heap_getnext returning EOS */ + ExecClearTuple(slot); + return slot; + } + + /* + * if we get here it means we have a new current scan tuple, so point to + * the proper return buffer and return the tuple. + */ + HEAPAMSLOTDEBUG_3; /* heap_getnext returning tuple */ + + pgstat_count_heap_getnext(scan->rs_rd); + return ExecStoreTuple(heap_copytuple(&(scan->rs_ctup)), + slot, InvalidBuffer, true); +} + /* * heap_fetch - retrieve tuple with given tid * diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 006f604dbb..010fef208e 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -310,6 +310,15 @@ heap_tableam_handler(PG_FUNCTION_ARGS) amroutine->slot_storageam = slot_tableam_handler; + amroutine->scan_begin = heap_beginscan; + amroutine->scansetlimits = heap_setscanlimits; + amroutine->scan_getnext = heap_getnext; + amroutine->scan_getnextslot = heap_getnextslot; + amroutine->scan_end = heap_endscan; + amroutine->scan_rescan = heap_rescan; + amroutine->scan_update_snapshot = heap_update_snapshot; + amroutine->hot_search_buffer = heap_hot_search_buffer; + amroutine->tuple_fetch = heapam_fetch; amroutine->tuple_insert = heapam_heap_insert; amroutine->tuple_delete = heapam_heap_delete; diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c index c8e06fdef3..4b709a65ac 100644 --- a/src/backend/access/index/genam.c +++ b/src/backend/access/index/genam.c @@ -20,6 +20,7 @@ #include "postgres.h" #include "access/relscan.h" +#include "access/tableam.h" #include "access/transam.h" #include "catalog/index.h" #include "lib/stringinfo.h" @@ -397,9 +398,9 @@ systable_beginscan(Relation heapRelation, * disadvantage; and there are no compensating advantages, because * it's unlikely that such scans will occur in parallel. */ - sysscan->scan = heap_beginscan_strat(heapRelation, snapshot, - nkeys, key, - true, false); + sysscan->scan = table_beginscan_strat(heapRelation, snapshot, + nkeys, key, + true, false); sysscan->iscan = NULL; } @@ -435,7 +436,7 @@ systable_getnext(SysScanDesc sysscan) elog(ERROR, "system catalog scans with lossy index conditions are not implemented"); } else - htup = heap_getnext(sysscan->scan, ForwardScanDirection); + htup = table_scan_getnext(sysscan->scan, ForwardScanDirection); return htup; } @@ -507,7 +508,7 @@ systable_endscan(SysScanDesc sysscan) index_close(sysscan->irel, AccessShareLock); } else - heap_endscan(sysscan->scan); + table_endscan(sysscan->scan); if (sysscan->snapshot) UnregisterSnapshot(sysscan->snapshot); diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 22b5cc921f..c6dc0bed8a 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -71,6 +71,7 @@ #include "access/amapi.h" #include "access/relscan.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/xlog.h" #include "catalog/index.h" @@ -605,12 +606,12 @@ index_fetch_heap(IndexScanDesc scan) /* Obtain share-lock on the buffer so we can examine visibility */ LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE); - got_heap_tuple = heap_hot_search_buffer(tid, scan->heapRelation, - scan->xs_cbuf, - scan->xs_snapshot, - &scan->xs_ctup, - &all_dead, - !scan->xs_continue_hot); + got_heap_tuple = table_hot_search_buffer(tid, scan->heapRelation, + scan->xs_cbuf, + scan->xs_snapshot, + &scan->xs_ctup, + &all_dead, + !scan->xs_continue_hot); LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK); if (got_heap_tuple) diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 907cce0724..1b47e76049 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -18,6 +18,7 @@ #include "access/heapam.h" #include "access/nbtree.h" #include "access/nbtxlog.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/xloginsert.h" #include "miscadmin.h" @@ -426,8 +427,8 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel, * that satisfies SnapshotDirty. This is necessary because we * have just a single index entry for the entire chain. */ - else if (heap_hot_search(&htid, heapRel, &SnapshotDirty, - &all_dead)) + else if (table_hot_search(&htid, heapRel, &SnapshotDirty, + &all_dead)) { TransactionId xwait; @@ -480,7 +481,7 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel, * entry. */ htid = itup->t_tid; - if (heap_hot_search(&htid, heapRel, SnapshotSelf, NULL)) + if (table_hot_search(&htid, heapRel, SnapshotSelf, NULL)) { /* Normal case --- it's still live */ } diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index 89c2ba3285..106373fb7d 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -1685,7 +1685,7 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2, /* Join parallel scan */ indexInfo = BuildIndexInfo(btspool->index); indexInfo->ii_Concurrent = btshared->isconcurrent; - scan = heap_beginscan_parallel(btspool->heap, &btshared->heapdesc); + scan = table_beginscan_parallel(btspool->heap, &btshared->heapdesc); reltuples = IndexBuildHeapScan(btspool->heap, btspool->index, indexInfo, true, _bt_build_callback, (void *) &buildstate, scan); diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c index af4e53b76e..ace187ba24 100644 --- a/src/backend/access/table/tableam.c +++ b/src/backend/access/table/tableam.c @@ -16,7 +16,9 @@ #include "access/tableam.h" #include "access/tableamapi.h" +#include "access/relscan.h" #include "utils/rel.h" +#include "utils/tqual.h" /* * table_fetch - retrieve tuple with given tid @@ -48,6 +50,184 @@ table_lock_tuple(Relation relation, ItemPointer tid, TableTuple * stuple, follow_updates, buffer, hufd); } +/* ---------------- + * heap_beginscan_parallel - join a parallel scan + * + * Caller must hold a suitable lock on the correct relation. + * ---------------- + */ +HeapScanDesc +table_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan) +{ + Snapshot snapshot; + + Assert(RelationGetRelid(relation) == parallel_scan->phs_relid); + + if (!parallel_scan->phs_snapshot_any) + { + /* Snapshot was serialized -- restore it */ + snapshot = RestoreSnapshot(parallel_scan->phs_snapshot_data); + RegisterSnapshot(snapshot); + } + else + { + /* SnapshotAny passed by caller (not serialized) */ + snapshot = SnapshotAny; + } + + return relation->rd_tableamroutine->scan_begin(relation, snapshot, 0, NULL, parallel_scan, + true, true, true, false, false, !parallel_scan->phs_snapshot_any); +} + +/* + * heap_setscanlimits - restrict range of a heapscan + * + * startBlk is the page to start at + * numBlks is number of pages to scan (InvalidBlockNumber means "all") + */ +void +table_setscanlimits(HeapScanDesc sscan, BlockNumber startBlk, BlockNumber numBlks) +{ + sscan->rs_rd->rd_tableamroutine->scansetlimits(sscan, startBlk, numBlks); +} + + +/* ---------------- + * heap_beginscan - begin relation scan + * + * heap_beginscan is the "standard" case. + * + * heap_beginscan_catalog differs in setting up its own temporary snapshot. + * + * heap_beginscan_strat offers an extended API that lets the caller control + * whether a nondefault buffer access strategy can be used, and whether + * syncscan can be chosen (possibly resulting in the scan not starting from + * block zero). Both of these default to true with plain heap_beginscan. + * + * heap_beginscan_bm is an alternative entry point for setting up a + * HeapScanDesc for a bitmap heap scan. Although that scan technology is + * really quite unlike a standard seqscan, there is just enough commonality + * to make it worth using the same data structure. + * + * heap_beginscan_sampling is an alternative entry point for setting up a + * HeapScanDesc for a TABLESAMPLE scan. As with bitmap scans, it's worth + * using the same data structure although the behavior is rather different. + * In addition to the options offered by heap_beginscan_strat, this call + * also allows control of whether page-mode visibility checking is used. + * ---------------- + */ +HeapScanDesc +table_beginscan(Relation relation, Snapshot snapshot, + int nkeys, ScanKey key) +{ + return relation->rd_tableamroutine->scan_begin(relation, snapshot, nkeys, key, NULL, + true, true, true, false, false, false); +} + +HeapScanDesc +table_beginscan_catalog(Relation relation, int nkeys, ScanKey key) +{ + Oid relid = RelationGetRelid(relation); + Snapshot snapshot = RegisterSnapshot(GetCatalogSnapshot(relid)); + + return relation->rd_tableamroutine->scan_begin(relation, snapshot, nkeys, key, NULL, + true, true, true, false, false, true); +} + +HeapScanDesc +table_beginscan_strat(Relation relation, Snapshot snapshot, + int nkeys, ScanKey key, + bool allow_strat, bool allow_sync) +{ + return relation->rd_tableamroutine->scan_begin(relation, snapshot, nkeys, key, NULL, + allow_strat, allow_sync, true, + false, false, false); +} + +HeapScanDesc +table_beginscan_bm(Relation relation, Snapshot snapshot, + int nkeys, ScanKey key) +{ + return relation->rd_tableamroutine->scan_begin(relation, snapshot, nkeys, key, NULL, + false, false, true, true, false, false); +} + +HeapScanDesc +table_beginscan_sampling(Relation relation, Snapshot snapshot, + int nkeys, ScanKey key, + bool allow_strat, bool allow_sync, bool allow_pagemode) +{ + return relation->rd_tableamroutine->scan_begin(relation, snapshot, nkeys, key, NULL, + allow_strat, allow_sync, allow_pagemode, + false, true, false); +} + +/* ---------------- + * heap_rescan - restart a relation scan + * ---------------- + */ +void +table_rescan(HeapScanDesc scan, + ScanKey key) +{ + scan->rs_rd->rd_tableamroutine->scan_rescan(scan, key, false, false, false, false); +} + +/* ---------------- + * heap_rescan_set_params - restart a relation scan after changing params + * + * This call allows changing the buffer strategy, syncscan, and pagemode + * options before starting a fresh scan. Note that although the actual use + * of syncscan might change (effectively, enabling or disabling reporting), + * the previously selected startblock will be kept. + * ---------------- + */ +void +table_rescan_set_params(HeapScanDesc scan, ScanKey key, + bool allow_strat, bool allow_sync, bool allow_pagemode) +{ + scan->rs_rd->rd_tableamroutine->scan_rescan(scan, key, true, + allow_strat, allow_sync, (allow_pagemode && IsMVCCSnapshot(scan->rs_snapshot))); +} + +/* ---------------- + * heap_endscan - end relation scan + * + * See how to integrate with index scans. + * Check handling if reldesc caching. + * ---------------- + */ +void +table_endscan(HeapScanDesc scan) +{ + scan->rs_rd->rd_tableamroutine->scan_end(scan); +} + + +/* ---------------- + * heap_update_snapshot + * + * Update snapshot info in heap scan descriptor. + * ---------------- + */ +void +table_scan_update_snapshot(HeapScanDesc scan, Snapshot snapshot) +{ + scan->rs_rd->rd_tableamroutine->scan_update_snapshot(scan, snapshot); +} + +TableTuple +table_scan_getnext(HeapScanDesc sscan, ScanDirection direction) +{ + return sscan->rs_rd->rd_tableamroutine->scan_getnext(sscan, direction); +} + +TupleTableSlot * +table_scan_getnextslot(HeapScanDesc sscan, ScanDirection direction, TupleTableSlot *slot) +{ + return sscan->rs_rd->rd_tableamroutine->scan_getnextslot(sscan, direction, slot); +} + /* * Insert a tuple from a slot into table AM routine */ @@ -87,6 +267,59 @@ table_update(Relation relation, ItemPointer otid, TupleTableSlot *slot, lockmode, IndexFunc, recheckIndexes); } +/* + * heap_hot_search_buffer - search HOT chain for tuple satisfying snapshot + * + * On entry, *tid is the TID of a tuple (either a simple tuple, or the root + * of a HOT chain), and buffer is the buffer holding this tuple. We search + * for the first chain member satisfying the given snapshot. If one is + * found, we update *tid to reference that tuple's offset number, and + * return true. If no match, return false without modifying *tid. + * + * heapTuple is a caller-supplied buffer. When a match is found, we return + * the tuple here, in addition to updating *tid. If no match is found, the + * contents of this buffer on return are undefined. + * + * If all_dead is not NULL, we check non-visible tuples to see if they are + * globally dead; *all_dead is set true if all members of the HOT chain + * are vacuumable, false if not. + * + * Unlike heap_fetch, the caller must already have pin and (at least) share + * lock on the buffer; it is still pinned/locked at exit. Also unlike + * heap_fetch, we do not report any pgstats count; caller may do so if wanted. + */ +bool +table_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer, + Snapshot snapshot, HeapTuple heapTuple, + bool *all_dead, bool first_call) +{ + return relation->rd_tableamroutine->hot_search_buffer(tid, relation, buffer, + snapshot, heapTuple, all_dead, first_call); +} + +/* + * heap_hot_search - search HOT chain for tuple satisfying snapshot + * + * This has the same API as heap_hot_search_buffer, except that the caller + * does not provide the buffer containing the page, rather we access it + * locally. + */ +bool +table_hot_search(ItemPointer tid, Relation relation, Snapshot snapshot, + bool *all_dead) +{ + bool result; + Buffer buffer; + HeapTupleData heapTuple; + + buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid)); + LockBuffer(buffer, BUFFER_LOCK_SHARE); + result = relation->rd_tableamroutine->hot_search_buffer(tid, relation, buffer, + snapshot, &heapTuple, all_dead, true); + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + ReleaseBuffer(buffer); + return result; +} /* * table_multi_insert - insert multiple tuple into a table diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 7e34bee63e..dde8c1f0a7 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -18,6 +18,7 @@ #include #include "access/htup_details.h" +#include "access/tableam.h" #include "access/xact.h" #include "access/xlog_internal.h" #include "bootstrap/bootstrap.h" @@ -588,18 +589,18 @@ boot_openrel(char *relname) { /* We can now load the pg_type data */ rel = heap_open(TypeRelationId, NoLock); - scan = heap_beginscan_catalog(rel, 0, NULL); + scan = table_beginscan_catalog(rel, 0, NULL); i = 0; - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tup = table_scan_getnext(scan, ForwardScanDirection)) != NULL) ++i; - heap_endscan(scan); + table_endscan(scan); app = Typ = ALLOC(struct typmap *, i + 1); while (i-- > 0) *app++ = ALLOC(struct typmap, 1); *app = NULL; - scan = heap_beginscan_catalog(rel, 0, NULL); + scan = table_beginscan_catalog(rel, 0, NULL); app = Typ; - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tup = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { (*app)->am_oid = HeapTupleGetOid(tup); memcpy((char *) &(*app)->am_typ, @@ -607,7 +608,7 @@ boot_openrel(char *relname) sizeof((*app)->am_typ)); app++; } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, NoLock); } @@ -918,25 +919,25 @@ gettype(char *type) } elog(DEBUG4, "external type: %s", type); rel = heap_open(TypeRelationId, NoLock); - scan = heap_beginscan_catalog(rel, 0, NULL); + scan = table_beginscan_catalog(rel, 0, NULL); i = 0; - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tup = table_scan_getnext(scan, ForwardScanDirection)) != NULL) ++i; - heap_endscan(scan); + table_endscan(scan); app = Typ = ALLOC(struct typmap *, i + 1); while (i-- > 0) *app++ = ALLOC(struct typmap, 1); *app = NULL; - scan = heap_beginscan_catalog(rel, 0, NULL); + scan = table_beginscan_catalog(rel, 0, NULL); app = Typ; - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tup = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { (*app)->am_oid = HeapTupleGetOid(tup); memmove((char *) &(*app++)->am_typ, (char *) GETSTRUCT(tup), sizeof((*app)->am_typ)); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, NoLock); return gettype(type); } diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 578e4c6592..08ef93a8eb 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -20,6 +20,7 @@ #include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/sysattr.h" #include "access/xact.h" #include "catalog/binary_upgrade.h" @@ -844,14 +845,14 @@ objectsInSchemaToOids(ObjectType objtype, List *nspnames) CharGetDatum(PROKIND_PROCEDURE)); rel = heap_open(ProcedureRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, keycount, key); + scan = table_beginscan_catalog(rel, keycount, key); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { objects = lappend_oid(objects, HeapTupleGetOid(tuple)); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, AccessShareLock); } break; @@ -889,14 +890,14 @@ getRelationsInNamespace(Oid namespaceId, char relkind) CharGetDatum(relkind)); rel = heap_open(RelationRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, 2, key); + scan = table_beginscan_catalog(rel, 2, key); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { relations = lappend_oid(relations, HeapTupleGetOid(tuple)); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, AccessShareLock); return relations; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9286e78bcc..0f31815638 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -27,6 +27,7 @@ #include "access/multixact.h" #include "access/relscan.h" #include "access/reloptions.h" +#include "access/tableam.h" #include "access/sysattr.h" #include "access/transam.h" #include "access/visibilitymap.h" @@ -2131,10 +2132,10 @@ index_update_stats(Relation rel, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(relid)); - pg_class_scan = heap_beginscan_catalog(pg_class, 1, key); - tuple = heap_getnext(pg_class_scan, ForwardScanDirection); + pg_class_scan = table_beginscan_catalog(pg_class, 1, key); + tuple = table_scan_getnext(pg_class_scan, ForwardScanDirection); tuple = heap_copytuple(tuple); - heap_endscan(pg_class_scan); + table_endscan(pg_class_scan); } else { @@ -2530,7 +2531,7 @@ IndexBuildHeapRangeScan(Relation heapRelation, else snapshot = SnapshotAny; - scan = heap_beginscan_strat(heapRelation, /* relation */ + scan = table_beginscan_strat(heapRelation, /* relation */ snapshot, /* snapshot */ 0, /* number of keys */ NULL, /* scan key */ @@ -2566,7 +2567,7 @@ IndexBuildHeapRangeScan(Relation heapRelation, /* set our scan endpoints */ if (!allow_sync) - heap_setscanlimits(scan, start_blockno, numblocks); + table_setscanlimits(scan, start_blockno, numblocks); else { /* syncscan can only be requested on whole relation */ @@ -2579,7 +2580,7 @@ IndexBuildHeapRangeScan(Relation heapRelation, /* * Scan all tuples in the base relation. */ - while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((heapTuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { bool tupleIsAlive; @@ -2923,7 +2924,7 @@ IndexBuildHeapRangeScan(Relation heapRelation, } } - heap_endscan(scan); + table_endscan(scan); /* we can now forget our snapshot, if set and registered by us */ if (need_unregister_snapshot) @@ -2994,14 +2995,14 @@ IndexCheckExclusion(Relation heapRelation, * Scan all live tuples in the base relation. */ snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = heap_beginscan_strat(heapRelation, /* relation */ - snapshot, /* snapshot */ - 0, /* number of keys */ - NULL, /* scan key */ - true, /* buffer access strategy OK */ - true); /* syncscan OK */ - - while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan_strat(heapRelation, /* relation */ + snapshot, /* snapshot */ + 0, /* number of keys */ + NULL, /* scan key */ + true, /* buffer access strategy OK */ + true); /* syncscan OK */ + + while ((heapTuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { CHECK_FOR_INTERRUPTS(); @@ -3037,7 +3038,7 @@ IndexCheckExclusion(Relation heapRelation, estate, true); } - heap_endscan(scan); + table_endscan(scan); UnregisterSnapshot(snapshot); ExecDropSingleTupleTableSlot(slot); @@ -3314,17 +3315,17 @@ validate_index_heapscan(Relation heapRelation, * here, because it's critical that we read from block zero forward to * match the sorted TIDs. */ - scan = heap_beginscan_strat(heapRelation, /* relation */ - snapshot, /* snapshot */ - 0, /* number of keys */ - NULL, /* scan key */ - true, /* buffer access strategy OK */ - false); /* syncscan not OK */ + scan = table_beginscan_strat(heapRelation, /* relation */ + snapshot, /* snapshot */ + 0, /* number of keys */ + NULL, /* scan key */ + true, /* buffer access strategy OK */ + false); /* syncscan not OK */ /* * Scan all tuples matching the snapshot. */ - while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((heapTuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { ItemPointer heapcursor = &heapTuple->t_self; ItemPointerData rootTuple; @@ -3483,7 +3484,7 @@ validate_index_heapscan(Relation heapRelation, } } - heap_endscan(scan); + table_endscan(scan); ExecDropSingleTupleTableSlot(slot); diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 558022647c..4e6c5df158 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -17,6 +17,7 @@ #include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/tupconvert.h" #include "access/sysattr.h" #include "catalog/indexing.h" diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index fd5c18426b..86f426ef32 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -16,6 +16,7 @@ #include "access/heapam.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" @@ -160,14 +161,14 @@ RemoveConversionById(Oid conversionOid) /* open pg_conversion */ rel = heap_open(ConversionRelationId, RowExclusiveLock); - scan = heap_beginscan_catalog(rel, 1, &scanKeyData); + scan = table_beginscan_catalog(rel, 1, &scanKeyData); /* search for the target tuple */ - if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection))) + if (HeapTupleIsValid(tuple = table_scan_getnext(scan, ForwardScanDirection))) CatalogTupleDelete(rel, &tuple->t_self); else elog(ERROR, "could not find tuple for conversion %u", conversionOid); - heap_endscan(scan); + table_endscan(scan); heap_close(rel, RowExclusiveLock); } diff --git a/src/backend/catalog/pg_db_role_setting.c b/src/backend/catalog/pg_db_role_setting.c index e123691923..7450bf0278 100644 --- a/src/backend/catalog/pg_db_role_setting.c +++ b/src/backend/catalog/pg_db_role_setting.c @@ -13,6 +13,7 @@ #include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "catalog/indexing.h" #include "catalog/objectaccess.h" #include "catalog/pg_db_role_setting.h" @@ -196,12 +197,12 @@ DropSetting(Oid databaseid, Oid roleid) numkeys++; } - scan = heap_beginscan_catalog(relsetting, numkeys, keys); - while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) + scan = table_beginscan_catalog(relsetting, numkeys, keys); + while (HeapTupleIsValid(tup = table_scan_getnext(scan, ForwardScanDirection))) { CatalogTupleDelete(relsetting, &tup->t_self); } - heap_endscan(scan); + table_endscan(scan); heap_close(relsetting, RowExclusiveLock); } diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index ec3bd1d22d..e565a14418 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -21,6 +21,7 @@ #include "access/hash.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/xact.h" #include "catalog/catalog.h" @@ -333,9 +334,9 @@ GetAllTablesPublicationRelations(void) BTEqualStrategyNumber, F_CHAREQ, CharGetDatum(RELKIND_RELATION)); - scan = heap_beginscan_catalog(classRel, 1, key); + scan = table_beginscan_catalog(classRel, 1, key); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { Oid relid = HeapTupleGetOid(tuple); Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple); @@ -344,7 +345,7 @@ GetAllTablesPublicationRelations(void) result = lappend_oid(result, relid); } - heap_endscan(scan); + table_endscan(scan); heap_close(classRel, AccessShareLock); return result; diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index 8705d8b1d3..4e42b10c47 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -19,6 +19,7 @@ #include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/xact.h" #include "catalog/indexing.h" @@ -417,12 +418,12 @@ RemoveSubscriptionRel(Oid subid, Oid relid) } /* Do the search and delete what we found. */ - scan = heap_beginscan_catalog(rel, nkeys, skey); - while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) + scan = table_beginscan_catalog(rel, nkeys, skey); + while (HeapTupleIsValid(tup = table_scan_getnext(scan, ForwardScanDirection))) { CatalogTupleDelete(rel, &tup->t_self); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, RowExclusiveLock); } diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 5e9462c63e..fcaec72026 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -929,7 +929,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, } else { - heapScan = heap_beginscan(OldHeap, SnapshotAny, 0, (ScanKey) NULL); + heapScan = table_beginscan(OldHeap, SnapshotAny, 0, (ScanKey) NULL); indexScan = NULL; } @@ -979,7 +979,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, } else { - tuple = heap_getnext(heapScan, ForwardScanDirection); + tuple = table_scan_getnext(heapScan, ForwardScanDirection); if (tuple == NULL) break; @@ -1065,7 +1065,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, if (indexScan != NULL) index_endscan(indexScan); if (heapScan != NULL) - heap_endscan(heapScan); + table_endscan(heapScan); /* * In scan-and-sort mode, complete the sort, then read out all live tuples @@ -1712,8 +1712,8 @@ get_tables_to_cluster(MemoryContext cluster_context) Anum_pg_index_indisclustered, BTEqualStrategyNumber, F_BOOLEQ, BoolGetDatum(true)); - scan = heap_beginscan_catalog(indRelation, 1, &entry); - while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan_catalog(indRelation, 1, &entry); + while ((indexTuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { index = (Form_pg_index) GETSTRUCT(indexTuple); @@ -1733,7 +1733,7 @@ get_tables_to_cluster(MemoryContext cluster_context) MemoryContextSwitchTo(old_context); } - heap_endscan(scan); + table_endscan(scan); relation_close(indRelation, AccessShareLock); diff --git a/src/backend/commands/constraint.c b/src/backend/commands/constraint.c index 90f19ad3dd..21c3b38969 100644 --- a/src/backend/commands/constraint.c +++ b/src/backend/commands/constraint.c @@ -13,6 +13,7 @@ */ #include "postgres.h" +#include "access/tableam.h" #include "catalog/index.h" #include "commands/trigger.h" #include "executor/executor.h" @@ -102,7 +103,7 @@ unique_key_recheck(PG_FUNCTION_ARGS) * removed. */ tmptid = new_row->t_self; - if (!heap_hot_search(&tmptid, trigdata->tg_relation, SnapshotSelf, NULL)) + if (!table_hot_search(&tmptid, trigdata->tg_relation, SnapshotSelf, NULL)) { /* * All rows in the HOT chain are dead, so skip the check. diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 020b857d74..0fbfcf1c78 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -2052,10 +2052,10 @@ CopyTo(CopyState cstate) values = (Datum *) palloc(num_phys_attrs * sizeof(Datum)); nulls = (bool *) palloc(num_phys_attrs * sizeof(bool)); - scandesc = heap_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL); + scandesc = table_beginscan(cstate->rel, GetActiveSnapshot(), 0, NULL); processed = 0; - while ((tuple = heap_getnext(scandesc, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scandesc, ForwardScanDirection)) != NULL) { CHECK_FOR_INTERRUPTS(); @@ -2067,7 +2067,7 @@ CopyTo(CopyState cstate) processed++; } - heap_endscan(scandesc); + table_endscan(scandesc); pfree(values); pfree(nulls); diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 5342f217c0..1ccc123b61 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -26,6 +26,7 @@ #include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/xact.h" #include "access/xloginsert.h" #include "access/xlogutils.h" @@ -590,8 +591,8 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) * each one to the new database. */ rel = heap_open(TableSpaceRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan_catalog(rel, 0, NULL); + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { Oid srctablespace = HeapTupleGetOid(tuple); Oid dsttablespace; @@ -643,7 +644,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) XLOG_DBASE_CREATE | XLR_SPECIAL_REL_UPDATE); } } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, AccessShareLock); /* @@ -1875,8 +1876,8 @@ remove_dbtablespaces(Oid db_id) HeapTuple tuple; rel = heap_open(TableSpaceRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan_catalog(rel, 0, NULL); + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { Oid dsttablespace = HeapTupleGetOid(tuple); char *dstpath; @@ -1917,7 +1918,7 @@ remove_dbtablespaces(Oid db_id) pfree(dstpath); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, AccessShareLock); } @@ -1942,8 +1943,8 @@ check_db_file_conflict(Oid db_id) HeapTuple tuple; rel = heap_open(TableSpaceRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan_catalog(rel, 0, NULL); + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { Oid dsttablespace = HeapTupleGetOid(tuple); char *dstpath; @@ -1966,7 +1967,7 @@ check_db_file_conflict(Oid db_id) pfree(dstpath); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, AccessShareLock); return result; diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 3a3223bffb..b830dc9992 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -18,6 +18,7 @@ #include "access/amapi.h" #include "access/htup_details.h" #include "access/reloptions.h" +#include "access/tableam.h" #include "access/sysattr.h" #include "access/xact.h" #include "catalog/catalog.h" @@ -2365,8 +2366,8 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, * rels will be processed indirectly by reindex_relation). */ relationRelation = heap_open(RelationRelationId, AccessShareLock); - scan = heap_beginscan_catalog(relationRelation, num_keys, scan_keys); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan_catalog(relationRelation, num_keys, scan_keys); + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); Oid relid = HeapTupleGetOid(tuple); @@ -2412,7 +2413,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, MemoryContextSwitchTo(old); } - heap_endscan(scan); + table_endscan(scan); heap_close(relationRelation, AccessShareLock); /* Now reindex each rel in a separate transaction */ diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f3bae024b1..398d5d27e3 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -4713,7 +4713,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) * checking all the constraints. */ snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = heap_beginscan(oldrel, snapshot, 0, NULL); + scan = table_beginscan(oldrel, snapshot, 0, NULL); /* * Switch to per-tuple memory context and reset it for each tuple @@ -4721,7 +4721,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) */ oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { if (tab->rewrite > 0) { @@ -4835,7 +4835,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) } MemoryContextSwitchTo(oldCxt); - heap_endscan(scan); + table_endscan(scan); UnregisterSnapshot(snapshot); ExecDropSingleTupleTableSlot(oldslot); @@ -5241,9 +5241,9 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior be BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(typeOid)); - scan = heap_beginscan_catalog(classRel, 1, key); + scan = table_beginscan_catalog(classRel, 1, key); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { if (behavior == DROP_RESTRICT) ereport(ERROR, @@ -5255,7 +5255,7 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior be result = lappend_oid(result, HeapTupleGetOid(tuple)); } - heap_endscan(scan); + table_endscan(scan); heap_close(classRel, AccessShareLock); return result; @@ -8476,7 +8476,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup) econtext->ecxt_scantuple = slot; snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = heap_beginscan(rel, snapshot, 0, NULL); + scan = table_beginscan(rel, snapshot, 0, NULL); /* * Switch to per-tuple memory context and reset it for each tuple @@ -8484,7 +8484,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup) */ oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { ExecStoreTuple(tuple, slot, InvalidBuffer, false); @@ -8499,7 +8499,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup) } MemoryContextSwitchTo(oldcxt); - heap_endscan(scan); + table_endscan(scan); UnregisterSnapshot(snapshot); ExecDropSingleTupleTableSlot(slot); FreeExecutorState(estate); @@ -8554,9 +8554,9 @@ validateForeignKeyConstraint(char *conname, * ereport(ERROR) and that's that. */ snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = heap_beginscan(rel, snapshot, 0, NULL); + scan = table_beginscan(rel, snapshot, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { FunctionCallInfoData fcinfo; TriggerData trigdata; @@ -8585,7 +8585,7 @@ validateForeignKeyConstraint(char *conname, RI_FKey_check_ins(&fcinfo); } - heap_endscan(scan); + table_endscan(scan); UnregisterSnapshot(snapshot); } @@ -11136,8 +11136,8 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt) ObjectIdGetDatum(orig_tablespaceoid)); rel = heap_open(RelationRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, 1, key); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan_catalog(rel, 1, key); + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { Oid relOid = HeapTupleGetOid(tuple); Form_pg_class relForm; @@ -11197,7 +11197,7 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt) relations = lappend_oid(relations, relOid); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, AccessShareLock); if (relations == NIL) diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index f7e9160a4f..dd721c63a9 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -53,6 +53,7 @@ #include "access/heapam.h" #include "access/reloptions.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/sysattr.h" #include "access/xact.h" #include "access/xlog.h" @@ -418,8 +419,8 @@ DropTableSpace(DropTableSpaceStmt *stmt) Anum_pg_tablespace_spcname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(tablespacename)); - scandesc = heap_beginscan_catalog(rel, 1, entry); - tuple = heap_getnext(scandesc, ForwardScanDirection); + scandesc = table_beginscan_catalog(rel, 1, entry); + tuple = table_scan_getnext(scandesc, ForwardScanDirection); if (!HeapTupleIsValid(tuple)) { @@ -436,7 +437,7 @@ DropTableSpace(DropTableSpaceStmt *stmt) (errmsg("tablespace \"%s\" does not exist, skipping", tablespacename))); /* XXX I assume I need one or both of these next two calls */ - heap_endscan(scandesc); + table_endscan(scandesc); heap_close(rel, NoLock); } return; @@ -463,7 +464,7 @@ DropTableSpace(DropTableSpaceStmt *stmt) */ CatalogTupleDelete(rel, &tuple->t_self); - heap_endscan(scandesc); + table_endscan(scandesc); /* * Remove any comments or security labels on this tablespace. @@ -927,8 +928,8 @@ RenameTableSpace(const char *oldname, const char *newname) Anum_pg_tablespace_spcname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(oldname)); - scan = heap_beginscan_catalog(rel, 1, entry); - tup = heap_getnext(scan, ForwardScanDirection); + scan = table_beginscan_catalog(rel, 1, entry); + tup = table_scan_getnext(scan, ForwardScanDirection); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), @@ -939,7 +940,7 @@ RenameTableSpace(const char *oldname, const char *newname) newtuple = heap_copytuple(tup); newform = (Form_pg_tablespace) GETSTRUCT(newtuple); - heap_endscan(scan); + table_endscan(scan); /* Must be owner */ if (!pg_tablespace_ownercheck(HeapTupleGetOid(newtuple), GetUserId())) @@ -957,15 +958,15 @@ RenameTableSpace(const char *oldname, const char *newname) Anum_pg_tablespace_spcname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(newname)); - scan = heap_beginscan_catalog(rel, 1, entry); - tup = heap_getnext(scan, ForwardScanDirection); + scan = table_beginscan_catalog(rel, 1, entry); + tup = table_scan_getnext(scan, ForwardScanDirection); if (HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("tablespace \"%s\" already exists", newname))); - heap_endscan(scan); + table_endscan(scan); /* OK, update the entry */ namestrcpy(&(newform->spcname), newname); @@ -1007,8 +1008,8 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) Anum_pg_tablespace_spcname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(stmt->tablespacename)); - scandesc = heap_beginscan_catalog(rel, 1, entry); - tup = heap_getnext(scandesc, ForwardScanDirection); + scandesc = table_beginscan_catalog(rel, 1, entry); + tup = table_scan_getnext(scandesc, ForwardScanDirection); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), @@ -1049,7 +1050,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) heap_freetuple(newtuple); /* Conclude heap scan. */ - heap_endscan(scandesc); + table_endscan(scandesc); heap_close(rel, NoLock); return tablespaceoid; @@ -1398,8 +1399,8 @@ get_tablespace_oid(const char *tablespacename, bool missing_ok) Anum_pg_tablespace_spcname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(tablespacename)); - scandesc = heap_beginscan_catalog(rel, 1, entry); - tuple = heap_getnext(scandesc, ForwardScanDirection); + scandesc = table_beginscan_catalog(rel, 1, entry); + tuple = table_scan_getnext(scandesc, ForwardScanDirection); /* We assume that there can be at most one matching tuple */ if (HeapTupleIsValid(tuple)) @@ -1407,7 +1408,7 @@ get_tablespace_oid(const char *tablespacename, bool missing_ok) else result = InvalidOid; - heap_endscan(scandesc); + table_endscan(scandesc); heap_close(rel, AccessShareLock); if (!OidIsValid(result) && !missing_ok) @@ -1444,8 +1445,8 @@ get_tablespace_name(Oid spc_oid) ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(spc_oid)); - scandesc = heap_beginscan_catalog(rel, 1, entry); - tuple = heap_getnext(scandesc, ForwardScanDirection); + scandesc = table_beginscan_catalog(rel, 1, entry); + tuple = table_scan_getnext(scandesc, ForwardScanDirection); /* We assume that there can be at most one matching tuple */ if (HeapTupleIsValid(tuple)) @@ -1453,7 +1454,7 @@ get_tablespace_name(Oid spc_oid) else result = NULL; - heap_endscan(scandesc); + table_endscan(scandesc); heap_close(rel, AccessShareLock); return result; diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 175ecc8b48..6bd67639d1 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -32,6 +32,7 @@ #include "postgres.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/xact.h" #include "catalog/binary_upgrade.h" #include "catalog/catalog.h" @@ -2383,8 +2384,8 @@ AlterDomainNotNull(List *names, bool notNull) /* Scan all tuples in this relation */ snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = heap_beginscan(testrel, snapshot, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan(testrel, snapshot, 0, NULL); + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { int i; @@ -2413,7 +2414,7 @@ AlterDomainNotNull(List *names, bool notNull) } } } - heap_endscan(scan); + table_endscan(scan); UnregisterSnapshot(snapshot); /* Close each rel after processing, but keep lock */ @@ -2779,8 +2780,8 @@ validateDomainConstraint(Oid domainoid, char *ccbin) /* Scan all tuples in this relation */ snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = heap_beginscan(testrel, snapshot, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan(testrel, snapshot, 0, NULL); + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { int i; @@ -2823,7 +2824,7 @@ validateDomainConstraint(Oid domainoid, char *ccbin) ResetExprContext(econtext); } - heap_endscan(scan); + table_endscan(scan); UnregisterSnapshot(snapshot); /* Hold relation lock till commit (XXX bad for concurrency) */ diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index d90cb9a902..5f2069902a 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -28,6 +28,7 @@ #include "access/heapam.h" #include "access/htup_details.h" #include "access/multixact.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/xact.h" #include "catalog/namespace.h" @@ -533,9 +534,9 @@ get_all_vacuum_rels(void) pgclass = heap_open(RelationRelationId, AccessShareLock); - scan = heap_beginscan_catalog(pgclass, 0, NULL); + scan = table_beginscan_catalog(pgclass, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); MemoryContext oldcontext; @@ -562,7 +563,7 @@ get_all_vacuum_rels(void) MemoryContextSwitchTo(oldcontext); } - heap_endscan(scan); + table_endscan(scan); heap_close(pgclass, AccessShareLock); return vacrels; @@ -1190,9 +1191,9 @@ vac_truncate_clog(TransactionId frozenXID, */ relation = heap_open(DatabaseRelationId, AccessShareLock); - scan = heap_beginscan_catalog(relation, 0, NULL); + scan = table_beginscan_catalog(relation, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { volatile FormData_pg_database *dbform = (Form_pg_database) GETSTRUCT(tuple); TransactionId datfrozenxid = dbform->datfrozenxid; @@ -1229,7 +1230,7 @@ vac_truncate_clog(TransactionId frozenXID, } } - heap_endscan(scan); + table_endscan(scan); heap_close(relation, AccessShareLock); diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 9e78421978..f4e35b5289 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -544,7 +544,7 @@ static bool IndexSupportsBackwardScan(Oid indexid) { bool result; - HeapTuple ht_idxrel; + TableTuple ht_idxrel; Form_pg_class idxrelrec; IndexAmRoutine *amroutine; diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c index 486d6986eb..26c8e5065e 100644 --- a/src/backend/executor/execIndexing.c +++ b/src/backend/executor/execIndexing.c @@ -650,7 +650,7 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index, Oid *index_collations = index->rd_indcollation; int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index); IndexScanDesc index_scan; - HeapTuple tup; + TableTuple tup; ScanKeyData scankeys[INDEX_MAX_KEYS]; SnapshotData DirtySnapshot; int i; @@ -732,12 +732,13 @@ retry: bool existing_isnull[INDEX_MAX_KEYS]; char *error_new; char *error_existing; + tuple_data t_data = table_tuple_get_data(heap, tup, TID); /* * Ignore the entry for the tuple we're trying to check. */ if (ItemPointerIsValid(tupleid) && - ItemPointerEquals(tupleid, &tup->t_self)) + ItemPointerEquals(tupleid, &(t_data.tid))) { if (found_self) /* should not happen */ elog(ERROR, "found self tuple multiple times in index \"%s\"", @@ -785,7 +786,8 @@ retry: DirtySnapshot.speculativeToken && TransactionIdPrecedes(GetCurrentTransactionId(), xwait)))) { - ctid_wait = tup->t_data->t_ctid; + t_data = table_tuple_get_data(heap, tup, CTID); + ctid_wait = t_data.tid; reason_wait = indexInfo->ii_ExclusionOps ? XLTW_RecheckExclusionConstr : XLTW_InsertIndex; index_endscan(index_scan); @@ -805,7 +807,10 @@ retry: { conflict = true; if (conflictTid) - *conflictTid = tup->t_self; + { + t_data = table_tuple_get_data(heap, tup, TID); + *conflictTid = t_data.tid; + } break; } diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index 53410c4cbf..b4fa287933 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -118,7 +118,7 @@ RelationFindReplTupleByIndex(Relation rel, Oid idxoid, TupleTableSlot *searchslot, TupleTableSlot *outslot) { - HeapTuple scantuple; + TableTuple scantuple; ScanKeyData skey[INDEX_MAX_KEYS]; IndexScanDesc scan; SnapshotData snap; @@ -234,8 +234,7 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot) { TupleTableSlot *scanslot; - HeapTuple scantuple; - HeapScanDesc scan; + TableScanDesc scan; SnapshotData snap; TransactionId xwait; bool found; @@ -245,19 +244,19 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, /* Start a heap scan. */ InitDirtySnapshot(snap); - scan = heap_beginscan(rel, &snap, 0, NULL); + scan = table_beginscan(rel, &snap, 0, NULL); scanslot = MakeSingleTupleTableSlot(desc); retry: found = false; - heap_rescan(scan, NULL); + table_rescan(scan, NULL); /* Try to find the tuple */ - while ((scantuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((scanslot = table_scan_getnextslot(scan, ForwardScanDirection, scanslot)) + && !TupIsNull(scanslot)) { - ExecStoreTuple(scantuple, scanslot, InvalidBuffer, false); if (!ExecSlotCompare(scanslot, searchslot)) continue; @@ -325,7 +324,7 @@ retry: } } - heap_endscan(scan); + table_endscan(scan); ExecDropSingleTupleTableSlot(scanslot); return found; diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 77fdc26fd0..bc7dd3ecc1 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -720,7 +720,7 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot) Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot) { - HeapTuple tup; + TableTuple tup; TupleDesc tupdesc; /* Fetch slot's contents in regular-physical-tuple form */ @@ -804,7 +804,7 @@ ExecHeapifySlot(TupleTableSlot *slot) TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot) { - HeapTuple newTuple; + TableTuple newTuple; MemoryContext oldContext; /* @@ -1145,7 +1145,7 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc) * values is an array of C strings, one for each attribute of the return tuple. * A NULL string pointer indicates we want to create a NULL field. */ -HeapTuple +TableTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) { TupleDesc tupdesc = attinmeta->tupdesc; @@ -1153,7 +1153,7 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) Datum *dvalues; bool *nulls; int i; - HeapTuple tuple; + TableTuple tuple; dvalues = (Datum *) palloc(natts * sizeof(Datum)); nulls = (bool *) palloc(natts * sizeof(bool)); diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 23545896d4..b19abe6783 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -181,7 +181,7 @@ static void sqlfunction_destroy(DestReceiver *self); * polymorphic arguments. */ SQLFunctionParseInfoPtr -prepare_sql_fn_parse_info(HeapTuple procedureTuple, +prepare_sql_fn_parse_info(TableTuple procedureTuple, Node *call_expr, Oid inputCollation) { @@ -597,7 +597,7 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK) MemoryContext fcontext; MemoryContext oldcontext; Oid rettype; - HeapTuple procedureTuple; + TableTuple procedureTuple; Form_pg_proc procedureStruct; SQLFunctionCachePtr fcache; List *raw_parsetree_list; diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 0fe0c22c1e..6366a3fb1f 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -2517,7 +2517,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) Oid inputTypes[FUNC_MAX_ARGS]; int numArguments; int numDirectArgs; - HeapTuple aggTuple; + TableTuple aggTuple; Form_pg_aggregate aggform; AclResult aclresult; Oid transfn_oid, @@ -2642,7 +2642,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) /* Check that aggregate owner has permission to call component fns */ { - HeapTuple procTuple; + TableTuple procTuple; Oid aggOwner; procTuple = SearchSysCache1(PROCOID, diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index bdb82db149..45c9baf6c8 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -38,6 +38,7 @@ #include #include "access/relscan.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/visibilitymap.h" #include "executor/execdebug.h" @@ -431,8 +432,8 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres) HeapTupleData heapTuple; ItemPointerSet(&tid, page, offnum); - if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot, - &heapTuple, NULL, true)) + if (table_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot, + &heapTuple, NULL, true)) scan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid); } } @@ -742,7 +743,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node) PlanState *outerPlan = outerPlanState(node); /* rescan to release any page pin */ - heap_rescan(node->ss.ss_currentScanDesc, NULL); + table_rescan(node->ss.ss_currentScanDesc, NULL); /* release bitmaps and buffers if any */ if (node->tbmiterator) @@ -832,7 +833,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node) /* * close heap scan */ - heap_endscan(scanDesc); + table_endscan(scanDesc); /* * close the heap relation. @@ -963,10 +964,10 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) * Even though we aren't going to do a conventional seqscan, it is useful * to create a HeapScanDesc --- most of the fields in it are usable. */ - scanstate->ss.ss_currentScanDesc = heap_beginscan_bm(currentRelation, - estate->es_snapshot, - 0, - NULL); + scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation, + estate->es_snapshot, + 0, + NULL); /* * all done. @@ -1114,5 +1115,5 @@ ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node, node->pstate = pstate; snapshot = RestoreSnapshot(pstate->phs_snapshot_data); - heap_update_snapshot(node->ss.ss_currentScanDesc, snapshot); + table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot); } diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index 869eebf274..a2e6470126 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -62,9 +62,9 @@ ForeignNext(ForeignScanState *node) */ if (plan->fsSystemCol && !TupIsNull(slot)) { - HeapTuple tup = ExecHeapifySlot(slot); - - tup->t_tableOid = RelationGetRelid(node->ss.ss_currentRelation); + ExecMaterializeSlot(slot); + ExecSlotUpdateTupleTableoid(slot, + RelationGetRelid(node->ss.ss_currentRelation)); } return slot; diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index cdc9c51bd1..5a0e33a752 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -46,7 +46,7 @@ static TupleTableSlot *ExecGather(PlanState *pstate); static TupleTableSlot *gather_getnext(GatherState *gatherstate); -static HeapTuple gather_readnext(GatherState *gatherstate); +static TableTuple gather_readnext(GatherState *gatherstate); static void ExecShutdownGatherWorkers(GatherState *node); @@ -245,7 +245,7 @@ gather_getnext(GatherState *gatherstate) PlanState *outerPlan = outerPlanState(gatherstate); TupleTableSlot *outerTupleSlot; TupleTableSlot *fslot = gatherstate->funnel_slot; - HeapTuple tup; + TableTuple tup; while (gatherstate->nreaders > 0 || gatherstate->need_to_scan_locally) { @@ -289,7 +289,7 @@ gather_getnext(GatherState *gatherstate) /* * Attempt to read a tuple from one of our parallel workers. */ -static HeapTuple +static TableTuple gather_readnext(GatherState *gatherstate) { int nvisited = 0; @@ -297,7 +297,7 @@ gather_readnext(GatherState *gatherstate) for (;;) { TupleQueueReader *reader; - HeapTuple tup; + TableTuple tup; bool readerdone; /* Check for async events, particularly messages from workers. */ diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c index a0b3334bed..158549dd6c 100644 --- a/src/backend/executor/nodeGatherMerge.c +++ b/src/backend/executor/nodeGatherMerge.c @@ -45,7 +45,7 @@ */ typedef struct GMReaderTupleBuffer { - HeapTuple *tuple; /* array of length MAX_TUPLE_STORE */ + TableTuple *tuple; /* array of length MAX_TUPLE_STORE */ int nTuples; /* number of tuples currently stored */ int readCounter; /* index of next tuple to extract */ bool done; /* true if reader is known exhausted */ @@ -54,8 +54,8 @@ typedef struct GMReaderTupleBuffer static TupleTableSlot *ExecGatherMerge(PlanState *pstate); static int32 heap_compare_slots(Datum a, Datum b, void *arg); static TupleTableSlot *gather_merge_getnext(GatherMergeState *gm_state); -static HeapTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader, - bool nowait, bool *done); +static TableTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader, + bool nowait, bool *done); static void ExecShutdownGatherMergeWorkers(GatherMergeState *node); static void gather_merge_setup(GatherMergeState *gm_state); static void gather_merge_init(GatherMergeState *gm_state); @@ -399,7 +399,7 @@ gather_merge_setup(GatherMergeState *gm_state) { /* Allocate the tuple array with length MAX_TUPLE_STORE */ gm_state->gm_tuple_buffers[i].tuple = - (HeapTuple *) palloc0(sizeof(HeapTuple) * MAX_TUPLE_STORE); + (TableTuple *) palloc0(sizeof(TableTuple) * MAX_TUPLE_STORE); /* Initialize tuple slot for worker */ gm_state->gm_slots[i + 1] = @@ -616,7 +616,7 @@ static bool gather_merge_readnext(GatherMergeState *gm_state, int reader, bool nowait) { GMReaderTupleBuffer *tuple_buffer; - HeapTuple tup; + TableTuple tup; /* * If we're being asked to generate a tuple from the leader, then we just @@ -691,12 +691,12 @@ gather_merge_readnext(GatherMergeState *gm_state, int reader, bool nowait) /* * Attempt to read a tuple from given worker. */ -static HeapTuple +static TableTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader, bool nowait, bool *done) { TupleQueueReader *reader; - HeapTuple tup; + TableTuple tup; /* Check for async events, particularly messages from workers. */ CHECK_FOR_INTERRUPTS(); diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 3a02a99621..379f992a80 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -117,7 +117,7 @@ IndexOnlyNext(IndexOnlyScanState *node) */ while ((tid = index_getnext_tid(scandesc, direction)) != NULL) { - HeapTuple tuple = NULL; + TableTuple tuple = NULL; CHECK_FOR_INTERRUPTS(); @@ -186,9 +186,9 @@ IndexOnlyNext(IndexOnlyScanState *node) /* * 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. + * provided in either TableTuple 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. */ if (scandesc->xs_hitup) { diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index d6012192a1..1da9ba8908 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -51,7 +51,7 @@ typedef struct { pairingheap_node ph_node; - HeapTuple htup; + TableTuple htup; Datum *orderbyvals; bool *orderbynulls; } ReorderTuple; @@ -65,9 +65,9 @@ static int cmp_orderbyvals(const Datum *adist, const bool *anulls, IndexScanState *node); static int reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg); -static void reorderqueue_push(IndexScanState *node, HeapTuple tuple, +static void reorderqueue_push(IndexScanState *node, TableTuple tuple, Datum *orderbyvals, bool *orderbynulls); -static HeapTuple reorderqueue_pop(IndexScanState *node); +static TableTuple reorderqueue_pop(IndexScanState *node); /* ---------------------------------------------------------------- @@ -84,7 +84,7 @@ IndexNext(IndexScanState *node) ExprContext *econtext; ScanDirection direction; IndexScanDesc scandesc; - HeapTuple tuple; + TableTuple tuple; TupleTableSlot *slot; /* @@ -184,7 +184,7 @@ IndexNextWithReorder(IndexScanState *node) EState *estate; ExprContext *econtext; IndexScanDesc scandesc; - HeapTuple tuple; + TableTuple tuple; TupleTableSlot *slot; ReorderTuple *topmost = NULL; bool was_exact; @@ -478,7 +478,7 @@ reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b, * Helper function to push a tuple to the reorder queue. */ static void -reorderqueue_push(IndexScanState *node, HeapTuple tuple, +reorderqueue_push(IndexScanState *node, TableTuple tuple, Datum *orderbyvals, bool *orderbynulls) { IndexScanDesc scandesc = node->iss_ScanDesc; @@ -511,10 +511,10 @@ reorderqueue_push(IndexScanState *node, HeapTuple tuple, /* * Helper function to pop the next tuple from the reorder queue. */ -static HeapTuple +static TableTuple reorderqueue_pop(IndexScanState *node) { - HeapTuple result; + TableTuple result; ReorderTuple *topmost; int i; diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c index 950f88100c..b3eda4e751 100644 --- a/src/backend/executor/nodeSamplescan.c +++ b/src/backend/executor/nodeSamplescan.c @@ -28,10 +28,12 @@ static TupleTableSlot *SampleNext(SampleScanState *node); static void tablesample_init(SampleScanState *scanstate); -static HeapTuple tablesample_getnext(SampleScanState *scanstate); -static bool SampleTupleVisible(HeapTuple tuple, OffsetNumber tupoffset, +static TableTuple tablesample_getnext(SampleScanState *scanstate); +static bool SampleTupleVisible(TableTuple tuple, OffsetNumber tupoffset, HeapScanDesc scan); +/* hari */ + /* ---------------------------------------------------------------- * Scan Support * ---------------------------------------------------------------- @@ -46,7 +48,7 @@ static bool SampleTupleVisible(HeapTuple tuple, OffsetNumber tupoffset, static TupleTableSlot * SampleNext(SampleScanState *node) { - HeapTuple tuple; + TableTuple tuple; TupleTableSlot *slot; /* @@ -222,7 +224,7 @@ ExecEndSampleScan(SampleScanState *node) * close heap scan */ if (node->ss.ss_currentScanDesc) - heap_endscan(node->ss.ss_currentScanDesc); + table_endscan(node->ss.ss_currentScanDesc); /* * close the heap relation. @@ -327,19 +329,19 @@ tablesample_init(SampleScanState *scanstate) if (scanstate->ss.ss_currentScanDesc == NULL) { scanstate->ss.ss_currentScanDesc = - heap_beginscan_sampling(scanstate->ss.ss_currentRelation, - scanstate->ss.ps.state->es_snapshot, - 0, NULL, - scanstate->use_bulkread, - allow_sync, - scanstate->use_pagemode); + table_beginscan_sampling(scanstate->ss.ss_currentRelation, + scanstate->ss.ps.state->es_snapshot, + 0, NULL, + scanstate->use_bulkread, + allow_sync, + scanstate->use_pagemode); } else { - heap_rescan_set_params(scanstate->ss.ss_currentScanDesc, NULL, - scanstate->use_bulkread, - allow_sync, - scanstate->use_pagemode); + table_rescan_set_params(scanstate->ss.ss_currentScanDesc, NULL, + scanstate->use_bulkread, + allow_sync, + scanstate->use_pagemode); } pfree(params); @@ -354,7 +356,7 @@ tablesample_init(SampleScanState *scanstate) * Note: an awful lot of this is copied-and-pasted from heapam.c. It would * perhaps be better to refactor to share more code. */ -static HeapTuple +static TableTuple tablesample_getnext(SampleScanState *scanstate) { TsmRoutine *tsm = scanstate->tsmroutine; @@ -532,7 +534,7 @@ tablesample_getnext(SampleScanState *scanstate) * Check visibility of the tuple. */ static bool -SampleTupleVisible(HeapTuple tuple, OffsetNumber tupoffset, HeapScanDesc scan) +SampleTupleVisible(TableTuple tuple, OffsetNumber tupoffset, HeapScanDesc scan) //hari { if (scan->rs_pageatatime) { diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index 9db368922a..758dbeb9c7 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -28,6 +28,7 @@ #include "postgres.h" #include "access/relscan.h" +#include "access/tableam.h" #include "executor/execdebug.h" #include "executor/nodeSeqscan.h" #include "utils/rel.h" @@ -48,8 +49,7 @@ static TupleTableSlot *SeqNext(SeqScanState *node); static TupleTableSlot * SeqNext(SeqScanState *node) { - HeapTuple tuple; - HeapScanDesc scandesc; + TableScanDesc scandesc; EState *estate; ScanDirection direction; TupleTableSlot *slot; @@ -68,35 +68,16 @@ SeqNext(SeqScanState *node) * We reach here if the scan is not parallel, or if we're executing a * scan that was intended to be parallel serially. */ - scandesc = heap_beginscan(node->ss.ss_currentRelation, - estate->es_snapshot, - 0, NULL); + scandesc = table_beginscan(node->ss.ss_currentRelation, + estate->es_snapshot, + 0, NULL); node->ss.ss_currentScanDesc = scandesc; } /* * get the next tuple from the table */ - tuple = heap_getnext(scandesc, direction); - - /* - * save the tuple and the buffer returned to us by the access methods in - * our scan tuple slot and return the slot. Note: we pass 'false' because - * tuples returned by heap_getnext() are pointers onto disk pages and were - * not created with palloc() and so should not be pfree()'d. Note also - * that ExecStoreTuple will increment the refcount of the buffer; the - * refcount will not be dropped until the tuple table slot is cleared. - */ - if (tuple) - ExecStoreTuple(tuple, /* tuple to store */ - slot, /* slot to store in */ - scandesc->rs_cbuf, /* buffer associated with this - * tuple */ - false); /* don't pfree this pointer */ - else - ExecClearTuple(slot); - - return slot; + return table_scan_getnextslot(scandesc, direction, slot); } /* @@ -203,7 +184,7 @@ void ExecEndSeqScan(SeqScanState *node) { Relation relation; - HeapScanDesc scanDesc; + TableScanDesc scanDesc; /* * get information from node @@ -226,7 +207,7 @@ ExecEndSeqScan(SeqScanState *node) * close heap scan */ if (scanDesc != NULL) - heap_endscan(scanDesc); + table_endscan(scanDesc); /* * close the heap relation. @@ -248,13 +229,13 @@ ExecEndSeqScan(SeqScanState *node) void ExecReScanSeqScan(SeqScanState *node) { - HeapScanDesc scan; + TableScanDesc scan; scan = node->ss.ss_currentScanDesc; if (scan != NULL) - heap_rescan(scan, /* scan desc */ - NULL); /* new scan keys */ + table_rescan(scan, /* scan desc */ + NULL); /* new scan keys */ ExecScanReScan((ScanState *) node); } @@ -301,7 +282,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node, estate->es_snapshot); shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan); node->ss.ss_currentScanDesc = - heap_beginscan_parallel(node->ss.ss_currentRelation, pscan); + table_beginscan_parallel(node->ss.ss_currentRelation, pscan); } /* ---------------------------------------------------------------- @@ -333,5 +314,5 @@ ExecSeqScanInitializeWorker(SeqScanState *node, pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false); node->ss.ss_currentScanDesc = - heap_beginscan_parallel(node->ss.ss_currentRelation, pscan); + table_beginscan_parallel(node->ss.ss_currentRelation, pscan); } diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 968d5d3771..84f9c94cae 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -2590,7 +2590,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc, { Oid inputTypes[FUNC_MAX_ARGS]; int numArguments; - HeapTuple aggTuple; + TableTuple aggTuple; Form_pg_aggregate aggform; Oid aggtranstype; AttrNumber initvalAttNo; @@ -2673,7 +2673,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc, /* Check that aggregate owner has permission to call component fns */ { - HeapTuple procTuple; + TableTuple procTuple; Oid aggOwner; procTuple = SearchSysCache1(PROCOID, diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 22dd55c378..79e6680216 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -723,11 +723,11 @@ SPI_freeplan(SPIPlanPtr plan) return 0; } -HeapTuple -SPI_copytuple(HeapTuple tuple) +TableTuple +SPI_copytuple(TableTuple tuple) { MemoryContext oldcxt; - HeapTuple ctuple; + TableTuple ctuple; if (tuple == NULL) { @@ -751,7 +751,7 @@ SPI_copytuple(HeapTuple tuple) } HeapTupleHeader -SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc) +SPI_returntuple(TableTuple tuple, TupleDesc tupdesc) { MemoryContext oldcxt; HeapTupleHeader dtup; @@ -782,7 +782,7 @@ SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc) return dtup; } -HeapTuple +TableTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum, Datum *Values, const char *Nulls) { @@ -950,7 +950,7 @@ char * SPI_gettype(TupleDesc tupdesc, int fnumber) { Oid typoid; - HeapTuple typeTuple; + TableTuple typeTuple; char *result; SPI_result = 0; @@ -1058,7 +1058,7 @@ SPI_datumTransfer(Datum value, bool typByVal, int typLen) } void -SPI_freetuple(HeapTuple tuple) +SPI_freetuple(TableTuple tuple) { /* No longer need to worry which context tuple was in... */ heap_freetuple(tuple); @@ -1779,7 +1779,7 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo) /* set up initial allocations */ tuptable->alloced = tuptable->free = 128; - tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple)); + tuptable->vals = (TableTuple *) palloc(tuptable->alloced * sizeof(TableTuple)); tuptable->tupdesc = CreateTupleDescCopy(typeinfo); MemoryContextSwitchTo(oldcxt); @@ -1810,8 +1810,8 @@ spi_printtup(TupleTableSlot *slot, DestReceiver *self) /* Double the size of the pointer array */ tuptable->free = tuptable->alloced; tuptable->alloced += tuptable->free; - tuptable->vals = (HeapTuple *) repalloc_huge(tuptable->vals, - tuptable->alloced * sizeof(HeapTuple)); + tuptable->vals = (TableTuple *) repalloc_huge(tuptable->vals, + tuptable->alloced * sizeof(TableTuple)); } tuptable->vals[tuptable->alloced - tuptable->free] = diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c index 12b9fef894..40ab871227 100644 --- a/src/backend/executor/tqueue.c +++ b/src/backend/executor/tqueue.c @@ -168,7 +168,7 @@ DestroyTupleQueueReader(TupleQueueReader *reader) * accumulate bytes from a partially-read message, so it's useful to call * this with nowait = true even if nothing is returned. */ -HeapTuple +TableTuple TupleQueueReaderNext(TupleQueueReader *reader, bool nowait, bool *done) { HeapTupleData htup; diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index b19c76acc8..8728d90b1c 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -13,6 +13,7 @@ */ #include "postgres.h" +#include "access/tableam.h" #include "catalog/partition.h" #include "catalog/pg_inherits.h" #include "catalog/pg_type.h" @@ -704,7 +705,7 @@ check_default_partition_contents(Relation parent, Relation default_rel, econtext = GetPerTupleExprContext(estate); snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = heap_beginscan(part_rel, snapshot, 0, NULL); + scan = table_beginscan(part_rel, snapshot, 0, NULL); tupslot = MakeSingleTupleTableSlot(tupdesc); /* @@ -713,7 +714,7 @@ check_default_partition_contents(Relation parent, Relation default_rel, */ oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { ExecStoreTuple(tuple, tupslot, InvalidBuffer, false); econtext->ecxt_scantuple = tupslot; @@ -729,7 +730,7 @@ check_default_partition_contents(Relation parent, Relation default_rel, } MemoryContextSwitchTo(oldCxt); - heap_endscan(scan); + table_endscan(scan); UnregisterSnapshot(snapshot); ExecDropSingleTupleTableSlot(tupslot); FreeExecutorState(estate); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 02e6d8131e..6a875c6d82 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -1896,9 +1896,9 @@ get_database_list(void) (void) GetTransactionSnapshot(); rel = heap_open(DatabaseRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, 0, NULL); + scan = table_beginscan_catalog(rel, 0, NULL); - while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) + while (HeapTupleIsValid(tup = table_scan_getnext(scan, ForwardScanDirection))) { Form_pg_database pgdatabase = (Form_pg_database) GETSTRUCT(tup); avw_dbase *avdb; @@ -1925,7 +1925,7 @@ get_database_list(void) MemoryContextSwitchTo(oldcxt); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, AccessShareLock); CommitTransactionCommand(); @@ -2056,13 +2056,13 @@ do_autovacuum(void) * wide tables there might be proportionally much more activity in the * TOAST table than in its parent. */ - relScan = heap_beginscan_catalog(classRel, 0, NULL); + relScan = table_beginscan_catalog(classRel, 0, NULL); /* * On the first pass, we collect main tables to vacuum, and also the main * table relid to TOAST relid mapping. */ - while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL) + while ((tuple = table_scan_getnext(relScan, ForwardScanDirection)) != NULL) { Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); PgStat_StatTabEntry *tabentry; @@ -2148,7 +2148,7 @@ do_autovacuum(void) } } - heap_endscan(relScan); + table_endscan(relScan); /* second pass: check TOAST tables */ ScanKeyInit(&key, @@ -2156,8 +2156,8 @@ do_autovacuum(void) BTEqualStrategyNumber, F_CHAREQ, CharGetDatum(RELKIND_TOASTVALUE)); - relScan = heap_beginscan_catalog(classRel, 1, &key); - while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL) + relScan = table_beginscan_catalog(classRel, 1, &key); + while ((tuple = table_scan_getnext(relScan, ForwardScanDirection)) != NULL) { Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); PgStat_StatTabEntry *tabentry; @@ -2203,7 +2203,7 @@ do_autovacuum(void) table_oids = lappend_oid(table_oids, relid); } - heap_endscan(relScan); + table_endscan(relScan); heap_close(classRel, AccessShareLock); /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 084573e77c..a0ca9ee127 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -36,6 +36,7 @@ #include "access/heapam.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/twophase_rmgr.h" #include "access/xact.h" @@ -1221,8 +1222,8 @@ pgstat_collect_oids(Oid catalogid) rel = heap_open(catalogid, AccessShareLock); snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = heap_beginscan(rel, snapshot, 0, NULL); - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = table_beginscan(rel, snapshot, 0, NULL); + while ((tup = table_scan_getnext(scan, ForwardScanDirection)) != NULL) { Oid thisoid = HeapTupleGetOid(tup); @@ -1230,7 +1231,7 @@ pgstat_collect_oids(Oid catalogid) (void) hash_search(htab, (void *) &thisoid, HASH_ENTER, NULL); } - heap_endscan(scan); + table_endscan(scan); UnregisterSnapshot(snapshot); heap_close(rel, AccessShareLock); diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index 6ef333b725..d98a3e891f 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -24,6 +24,7 @@ #include "access/heapam.h" #include "access/htup.h" #include "access/htup_details.h" +#include "access/tableam.h" #include "access/xact.h" #include "catalog/pg_subscription.h" @@ -124,9 +125,9 @@ get_subscription_list(void) (void) GetTransactionSnapshot(); rel = heap_open(SubscriptionRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, 0, NULL); + scan = table_beginscan_catalog(rel, 0, NULL); - while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) + while (HeapTupleIsValid(tup = table_scan_getnext(scan, ForwardScanDirection))) { Form_pg_subscription subform = (Form_pg_subscription) GETSTRUCT(tup); Subscription *sub; @@ -152,7 +153,7 @@ get_subscription_list(void) MemoryContextSwitchTo(oldcxt); } - heap_endscan(scan); + table_endscan(scan); heap_close(rel, AccessShareLock); CommitTransactionCommand(); diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index d81a2ea342..0992fb7fd8 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -17,6 +17,7 @@ #include "access/heapam.h" #include "access/htup_details.h" #include "access/multixact.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/xact.h" #include "catalog/catalog.h" @@ -435,13 +436,13 @@ DefineQueryRewrite(const char *rulename, RelationGetRelationName(event_relation)))); snapshot = RegisterSnapshot(GetLatestSnapshot()); - scanDesc = heap_beginscan(event_relation, snapshot, 0, NULL); - if (heap_getnext(scanDesc, ForwardScanDirection) != NULL) + scanDesc = table_beginscan(event_relation, snapshot, 0, NULL); + if (table_scan_getnext(scanDesc, ForwardScanDirection) != NULL) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("could not convert table \"%s\" to a view because it is not empty", RelationGetRelationName(event_relation)))); - heap_endscan(scanDesc); + table_endscan(scanDesc); UnregisterSnapshot(snapshot); if (event_relation->rd_rel->relhastriggers) diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 09e0df290d..99841b669b 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -22,6 +22,7 @@ #include "access/heapam.h" #include "access/htup_details.h" #include "access/session.h" +#include "access/tableam.h" #include "access/sysattr.h" #include "access/xact.h" #include "access/xlog.h" @@ -1218,10 +1219,10 @@ ThereIsAtLeastOneRole(void) pg_authid_rel = heap_open(AuthIdRelationId, AccessShareLock); - scan = heap_beginscan_catalog(pg_authid_rel, 0, NULL); - result = (heap_getnext(scan, ForwardScanDirection) != NULL); + scan = table_beginscan_catalog(pg_authid_rel, 0, NULL); + result = (table_scan_getnext(scan, ForwardScanDirection) != NULL); - heap_endscan(scan); + table_endscan(scan); heap_close(pg_authid_rel, AccessShareLock); return result; diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index f660807147..429b065634 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -108,26 +108,25 @@ typedef struct ParallelHeapScanDescData *ParallelHeapScanDesc; #define HeapScanIsValid(scan) PointerIsValid(scan) extern HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot, - int nkeys, ScanKey key); -extern HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, - ScanKey key); -extern HeapScanDesc heap_beginscan_strat(Relation relation, Snapshot snapshot, - int nkeys, ScanKey key, - bool allow_strat, bool allow_sync); -extern HeapScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, - int nkeys, ScanKey key); -extern HeapScanDesc heap_beginscan_sampling(Relation relation, - Snapshot snapshot, int nkeys, ScanKey key, - bool allow_strat, bool allow_sync, bool allow_pagemode); + int nkeys, ScanKey key, + ParallelHeapScanDesc parallel_scan, + bool allow_strat, + bool allow_sync, + bool allow_pagemode, + bool is_bitmapscan, + bool is_samplescan, + bool temp_snap); extern void heap_setscanlimits(HeapScanDesc scan, BlockNumber startBlk, BlockNumber endBlk); extern void heapgetpage(HeapScanDesc scan, BlockNumber page); -extern void heap_rescan(HeapScanDesc scan, ScanKey key); +extern void heap_rescan(HeapScanDesc scan, ScanKey key, bool set_params, + bool allow_strat, bool allow_sync, bool allow_pagemode); extern void heap_rescan_set_params(HeapScanDesc scan, ScanKey key, bool allow_strat, bool allow_sync, bool allow_pagemode); extern void heap_endscan(HeapScanDesc scan); -extern HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction); - +extern TableTuple heap_getnext(HeapScanDesc scan, ScanDirection direction); +extern TupleTableSlot *heap_getnextslot(HeapScanDesc sscan, ScanDirection direction, + TupleTableSlot *slot); extern Size heap_parallelscan_estimate(Snapshot snapshot); extern void heap_parallelscan_initialize(ParallelHeapScanDesc target, Relation relation, Snapshot snapshot); diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index 1df7adf209..f3982c3c13 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -42,6 +42,34 @@ typedef List *(*InsertIndexTuples) (TupleTableSlot *slot, EState *estate, bool n /* Function pointer to let the index tuple delete from storage am */ typedef void (*DeleteIndexTuples) (Relation rel, ItemPointer tid, TransactionId old_xmin); +extern HeapScanDesc table_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan); + +extern void table_setscanlimits(HeapScanDesc sscan, BlockNumber startBlk, BlockNumber numBlks); +extern HeapScanDesc table_beginscan(Relation relation, Snapshot snapshot, + int nkeys, ScanKey key); +extern HeapScanDesc table_beginscan_catalog(Relation relation, int nkeys, ScanKey key); +extern HeapScanDesc table_beginscan_strat(Relation relation, Snapshot snapshot, + int nkeys, ScanKey key, + bool allow_strat, bool allow_sync); +extern HeapScanDesc table_beginscan_bm(Relation relation, Snapshot snapshot, + int nkeys, ScanKey key); +extern HeapScanDesc table_beginscan_sampling(Relation relation, Snapshot snapshot, + int nkeys, ScanKey key, + bool allow_strat, bool allow_sync, bool allow_pagemode); + +extern void table_endscan(HeapScanDesc scan); +extern void table_rescan(HeapScanDesc scan, ScanKey key); +extern void table_rescan_set_params(HeapScanDesc scan, ScanKey key, + bool allow_strat, bool allow_sync, bool allow_pagemode); +extern void table_scan_update_snapshot(HeapScanDesc scan, Snapshot snapshot); + +extern TableTuple table_scan_getnext(HeapScanDesc sscan, ScanDirection direction); +extern TupleTableSlot *table_scan_getnextslot(HeapScanDesc sscan, ScanDirection direction, TupleTableSlot *slot); + +extern void storage_get_latest_tid(Relation relation, + Snapshot snapshot, + ItemPointer tid); + extern bool table_fetch(Relation relation, ItemPointer tid, Snapshot snapshot, @@ -50,6 +78,13 @@ extern bool table_fetch(Relation relation, bool keep_buf, Relation stats_relation); +extern bool table_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer, + Snapshot snapshot, HeapTuple heapTuple, + bool *all_dead, bool first_call); + +extern bool table_hot_search(ItemPointer tid, Relation relation, Snapshot snapshot, + bool *all_dead); + extern HTSU_Result table_lock_tuple(Relation relation, ItemPointer tid, TableTuple * stuple, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, bool follow_updates, diff --git a/src/include/access/tableam_common.h b/src/include/access/tableam_common.h index e5cc461bd8..36b72e9767 100644 --- a/src/include/access/tableam_common.h +++ b/src/include/access/tableam_common.h @@ -28,6 +28,7 @@ /* A physical tuple coming from a table AM scan */ typedef void *TableTuple; +typedef void *TableScanDesc; /* Result codes for HeapTupleSatisfiesVacuum */ typedef enum diff --git a/src/include/access/tableamapi.h b/src/include/access/tableamapi.h index 8b9812068a..2ab3ba62d1 100644 --- a/src/include/access/tableamapi.h +++ b/src/include/access/tableamapi.h @@ -82,6 +82,39 @@ typedef TableTuple(*TupleFromDatum_function) (Datum data, Oid tableoid); typedef void (*RelationSync_function) (Relation relation); + +typedef HeapScanDesc (*ScanBegin_function) (Relation relation, + Snapshot snapshot, + int nkeys, ScanKey key, + ParallelHeapScanDesc parallel_scan, + bool allow_strat, + bool allow_sync, + bool allow_pagemode, + bool is_bitmapscan, + bool is_samplescan, + bool temp_snap); +typedef void (*ScanSetlimits_function) (HeapScanDesc sscan, BlockNumber startBlk, BlockNumber numBlks); + +/* must return a TupleTableSlot? */ +typedef TableTuple(*ScanGetnext_function) (HeapScanDesc scan, + ScanDirection direction); + +typedef TupleTableSlot *(*ScanGetnextSlot_function) (HeapScanDesc scan, + ScanDirection direction, TupleTableSlot *slot); + +typedef void (*ScanEnd_function) (HeapScanDesc scan); + + +typedef void (*ScanGetpage_function) (HeapScanDesc scan, BlockNumber page); +typedef void (*ScanRescan_function) (HeapScanDesc scan, ScanKey key, bool set_params, + bool allow_strat, bool allow_sync, bool allow_pagemode); +typedef void (*ScanUpdateSnapshot_function) (HeapScanDesc scan, Snapshot snapshot); + +typedef bool (*HotSearchBuffer_function) (ItemPointer tid, Relation relation, + Buffer buffer, Snapshot snapshot, HeapTuple heapTuple, + bool *all_dead, bool first_call); + + /* * API struct for a table AM. Note this must be stored in a single palloc'd * chunk of memory. @@ -115,6 +148,17 @@ typedef struct TableAmRoutine RelationSync_function relation_sync; /* heap_sync */ + /* Operations on relation scans */ + ScanBegin_function scan_begin; + ScanSetlimits_function scansetlimits; + ScanGetnext_function scan_getnext; + ScanGetnextSlot_function scan_getnextslot; + ScanEnd_function scan_end; + ScanGetpage_function scan_getpage; + ScanRescan_function scan_rescan; + ScanUpdateSnapshot_function scan_update_snapshot; + HotSearchBuffer_function hot_search_buffer; /* heap_hot_search_buffer */ + } TableAmRoutine; extern TableAmRoutine * GetTableAmRoutine(Oid amhandler); diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h index a309809ba8..fbf3c898f7 100644 --- a/src/include/executor/functions.h +++ b/src/include/executor/functions.h @@ -22,7 +22,7 @@ typedef struct SQLFunctionParseInfo *SQLFunctionParseInfoPtr; extern Datum fmgr_sql(PG_FUNCTION_ARGS); -extern SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, +extern SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(TableTuple procedureTuple, Node *call_expr, Oid inputCollation); diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index 143a89a16c..cbf372ffcb 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -25,7 +25,7 @@ typedef struct SPITupleTable uint64 alloced; /* # of alloced vals */ uint64 free; /* # of free vals */ TupleDesc tupdesc; /* tuple descriptor */ - HeapTuple *vals; /* tuples */ + TableTuple *vals; /* tuples */ slist_node next; /* link for internal bookkeeping */ SubTransactionId subid; /* subxact in which tuptable was created */ } SPITupleTable; @@ -120,10 +120,10 @@ extern const char *SPI_result_code_string(int code); extern List *SPI_plan_get_plan_sources(SPIPlanPtr plan); extern CachedPlan *SPI_plan_get_cached_plan(SPIPlanPtr plan); -extern HeapTuple SPI_copytuple(HeapTuple tuple); -extern HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc); -extern HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, - int *attnum, Datum *Values, const char *Nulls); +extern TableTuple SPI_copytuple(TableTuple tuple); +extern HeapTupleHeader SPI_returntuple(TableTuple tuple, TupleDesc tupdesc); +extern TableTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, + int *attnum, Datum *Values, const char *Nulls); extern int SPI_fnumber(TupleDesc tupdesc, const char *fname); extern char *SPI_fname(TupleDesc tupdesc, int fnumber); extern char *SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber); @@ -136,7 +136,7 @@ extern void *SPI_palloc(Size size); extern void *SPI_repalloc(void *pointer, Size size); extern void SPI_pfree(void *pointer); extern Datum SPI_datumTransfer(Datum value, bool typByVal, int typLen); -extern void SPI_freetuple(HeapTuple pointer); +extern void SPI_freetuple(TableTuple pointer); extern void SPI_freetuptable(SPITupleTable *tuptable); extern Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, diff --git a/src/include/executor/tqueue.h b/src/include/executor/tqueue.h index 0fe3639252..4635985222 100644 --- a/src/include/executor/tqueue.h +++ b/src/include/executor/tqueue.h @@ -26,7 +26,7 @@ extern DestReceiver *CreateTupleQueueDestReceiver(shm_mq_handle *handle); /* Use these to receive tuples from a shm_mq. */ extern TupleQueueReader *CreateTupleQueueReader(shm_mq_handle *handle); extern void DestroyTupleQueueReader(TupleQueueReader *reader); -extern HeapTuple TupleQueueReaderNext(TupleQueueReader *reader, - bool nowait, bool *done); +extern TableTuple TupleQueueReaderNext(TupleQueueReader *reader, + bool nowait, bool *done); #endif /* TQUEUE_H */ diff --git a/src/include/funcapi.h b/src/include/funcapi.h index 01aa208c5e..0f3e86d81f 100644 --- a/src/include/funcapi.h +++ b/src/include/funcapi.h @@ -238,7 +238,7 @@ extern TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases); /* from execTuples.c */ extern TupleDesc BlessTupleDesc(TupleDesc tupdesc); extern AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc); -extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values); +extern TableTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values); extern Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple); extern TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc); -- 2.16.1.windows.4