[PATCH 1/6] Pass the number of ScanKeys to scan_rescan()
Julien Tachoires <julien@tachoires.me>
From: Julien Tachoires <julien@tachoires.me>
To:
Date: 2025-08-25T15:01:57Z
Lists: pgsql-hackers
The number of ScanKeys passed to the table AM API routine scan_rescan()
was not specified, forcing the table AM to keep in memory the initial
number of ScanKeys passed via scan_begin(). Currenlty, there isn't any
real use of the ScanKeys during a table scan, so, this is not an issue,
but it could become a blocking point in the future if we want to
implement quals push down - as ScanKeys - to the table AM. Due to
runtime keys evaluation, this number of ScanKeys can vary between the
initial call to scan_begin() and a potential further call
to scan_rescan().
table_rescan() is modified in order to reflect the changes on
scan_rescan().
table_beginscan_parallel() signature is slightly modified in order to
pass eventual ScanKeys and their numbers to scan_begin().
table_rescan_set_params() now takes the number of ScanKeys as a new
argument.
---
src/backend/access/brin/brin.c | 3 ++-
src/backend/access/gin/gininsert.c | 3 ++-
src/backend/access/heap/heapam.c | 2 +-
src/backend/access/nbtree/nbtsort.c | 3 ++-
src/backend/access/table/tableam.c | 5 +++--
src/backend/executor/execReplication.c | 4 ++--
src/backend/executor/nodeBitmapHeapscan.c | 2 +-
src/backend/executor/nodeSamplescan.c | 2 +-
src/backend/executor/nodeSeqscan.c | 5 +++--
src/backend/executor/nodeTidscan.c | 2 +-
src/include/access/heapam.h | 5 +++--
src/include/access/tableam.h | 24 +++++++++++++----------
12 files changed, 35 insertions(+), 25 deletions(-)
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 7ff7467e462..5995bd1243e 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -2828,7 +2828,8 @@ _brin_parallel_scan_and_build(BrinBuildState *state,
indexInfo->ii_Concurrent = brinshared->isconcurrent;
scan = table_beginscan_parallel(heap,
- ParallelTableScanFromBrinShared(brinshared));
+ ParallelTableScanFromBrinShared(brinshared),
+ 0, NULL);
reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
brinbuildCallbackParallel, state, scan);
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index e9d4b27427e..deaa42cffa4 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -2030,7 +2030,8 @@ _gin_parallel_scan_and_build(GinBuildState *state,
indexInfo->ii_Concurrent = ginshared->isconcurrent;
scan = table_beginscan_parallel(heap,
- ParallelTableScanFromGinBuildShared(ginshared));
+ ParallelTableScanFromGinBuildShared(ginshared),
+ 0, NULL);
reltuples = table_index_build_scan(heap, index, indexInfo, true, progress,
ginBuildCallbackParallel, state, scan);
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 7491cc3cb93..a5c74d8948e 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1251,7 +1251,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
}
void
-heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
+heap_rescan(TableScanDesc sscan, int nkeys, ScanKey key, bool set_params,
bool allow_strat, bool allow_sync, bool allow_pagemode)
{
HeapScanDesc scan = (HeapScanDesc) sscan;
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 8828a7a8f89..d576ba3a762 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -1927,7 +1927,8 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
indexInfo = BuildIndexInfo(btspool->index);
indexInfo->ii_Concurrent = btshared->isconcurrent;
scan = table_beginscan_parallel(btspool->heap,
- ParallelTableScanFromBTShared(btshared));
+ ParallelTableScanFromBTShared(btshared),
+ 0, NULL);
reltuples = table_index_build_scan(btspool->heap, btspool->index, indexInfo,
true, progress, _bt_build_callback,
&buildstate, scan);
diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index a56c5eceb14..46bed1614f0 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -163,7 +163,8 @@ table_parallelscan_initialize(Relation rel, ParallelTableScanDesc pscan,
}
TableScanDesc
-table_beginscan_parallel(Relation relation, ParallelTableScanDesc pscan)
+table_beginscan_parallel(Relation relation, ParallelTableScanDesc pscan,
+ int nkeys, struct ScanKeyData *key)
{
Snapshot snapshot;
uint32 flags = SO_TYPE_SEQSCAN |
@@ -184,7 +185,7 @@ table_beginscan_parallel(Relation relation, ParallelTableScanDesc pscan)
snapshot = SnapshotAny;
}
- return relation->rd_tableam->scan_begin(relation, snapshot, 0, NULL,
+ return relation->rd_tableam->scan_begin(relation, snapshot, nkeys, key,
pscan, flags);
}
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index b409d4ecbf5..1b0c97243a5 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -388,7 +388,7 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
retry:
found = false;
- table_rescan(scan, NULL);
+ table_rescan(scan, 0, NULL);
/* Try to find the tuple */
while (table_scan_getnextslot(scan, ForwardScanDirection, scanslot))
@@ -604,7 +604,7 @@ RelationFindDeletedTupleInfoSeq(Relation rel, TupleTableSlot *searchslot,
scan = table_beginscan(rel, SnapshotAny, 0, NULL);
scanslot = table_slot_create(rel, NULL);
- table_rescan(scan, NULL);
+ table_rescan(scan, 0, NULL);
/* Try to find the tuple */
while (table_scan_getnextslot(scan, ForwardScanDirection, scanslot))
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index bf24f3d7fe0..fb778e0ae3b 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -239,7 +239,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
tbm_end_iterate(&scan->st.rs_tbmiterator);
/* rescan to release any page pin */
- table_rescan(node->ss.ss_currentScanDesc, NULL);
+ table_rescan(node->ss.ss_currentScanDesc, 0, NULL);
}
/* release bitmaps and buffers if any */
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 6b3db7548ed..a7e172d83a4 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -301,7 +301,7 @@ tablesample_init(SampleScanState *scanstate)
}
else
{
- table_rescan_set_params(scanstate->ss.ss_currentScanDesc, NULL,
+ table_rescan_set_params(scanstate->ss.ss_currentScanDesc, 0, NULL,
scanstate->use_bulkread,
allow_sync,
scanstate->use_pagemode);
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 94047d29430..c89aa6c6616 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -326,6 +326,7 @@ ExecReScanSeqScan(SeqScanState *node)
if (scan != NULL)
table_rescan(scan, /* scan desc */
+ 0, /* number of scan keys */
NULL); /* new scan keys */
ExecScanReScan((ScanState *) node);
@@ -374,7 +375,7 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
estate->es_snapshot);
shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
node->ss.ss_currentScanDesc =
- table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
+ table_beginscan_parallel(node->ss.ss_currentRelation, pscan, 0, NULL);
}
/* ----------------------------------------------------------------
@@ -407,5 +408,5 @@ ExecSeqScanInitializeWorker(SeqScanState *node,
pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
node->ss.ss_currentScanDesc =
- table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
+ table_beginscan_parallel(node->ss.ss_currentRelation, pscan, 0, NULL);
}
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 5e56e29a15f..6b37d1fcb74 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -454,7 +454,7 @@ ExecReScanTidScan(TidScanState *node)
/* not really necessary, but seems good form */
if (node->ss.ss_currentScanDesc)
- table_rescan(node->ss.ss_currentScanDesc, NULL);
+ table_rescan(node->ss.ss_currentScanDesc, 0, NULL);
ExecScanReScan(&node->ss);
}
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index a2bd5a897f8..252f5e661c1 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -293,8 +293,9 @@ extern TableScanDesc heap_beginscan(Relation relation, Snapshot snapshot,
extern void heap_setscanlimits(TableScanDesc sscan, BlockNumber startBlk,
BlockNumber numBlks);
extern void heap_prepare_pagescan(TableScanDesc sscan);
-extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
- bool allow_strat, bool allow_sync, bool allow_pagemode);
+extern void heap_rescan(TableScanDesc sscan, int nkeys, ScanKey key,
+ bool set_params, bool allow_strat, bool allow_sync,
+ bool allow_pagemode);
extern void heap_endscan(TableScanDesc sscan);
extern HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction);
extern bool heap_getnextslot(TableScanDesc sscan,
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 1c9e802a6b1..6fa0fa55a33 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -334,9 +334,10 @@ typedef struct TableAmRoutine
* Restart relation scan. If set_params is set to true, allow_{strat,
* sync, pagemode} (see scan_begin) changes should be taken into account.
*/
- void (*scan_rescan) (TableScanDesc scan, struct ScanKeyData *key,
- bool set_params, bool allow_strat,
- bool allow_sync, bool allow_pagemode);
+ void (*scan_rescan) (TableScanDesc scan, int nkeys,
+ struct ScanKeyData *key, bool set_params,
+ bool allow_strat, bool allow_sync,
+ bool allow_pagemode);
/*
* Return next tuple from `scan`, store in slot.
@@ -985,10 +986,10 @@ table_endscan(TableScanDesc scan)
* Restart a relation scan.
*/
static inline void
-table_rescan(TableScanDesc scan,
- struct ScanKeyData *key)
+table_rescan(TableScanDesc scan, int nkeys, struct ScanKeyData *key)
{
- scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
+ scan->rs_rd->rd_tableam->scan_rescan(scan, nkeys, key, false, false, false,
+ false);
}
/*
@@ -1000,10 +1001,10 @@ table_rescan(TableScanDesc scan,
* previously selected startblock will be kept.
*/
static inline void
-table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
+table_rescan_set_params(TableScanDesc scan, int nkeys, struct ScanKeyData *key,
bool allow_strat, bool allow_sync, bool allow_pagemode)
{
- scan->rs_rd->rd_tableam->scan_rescan(scan, key, true,
+ scan->rs_rd->rd_tableam->scan_rescan(scan, nkeys, key, true,
allow_strat, allow_sync,
allow_pagemode);
}
@@ -1068,7 +1069,8 @@ table_rescan_tidrange(TableScanDesc sscan, ItemPointer mintid,
/* Ensure table_beginscan_tidrange() was used. */
Assert((sscan->rs_flags & SO_TYPE_TIDRANGESCAN) != 0);
- sscan->rs_rd->rd_tableam->scan_rescan(sscan, NULL, false, false, false, false);
+ sscan->rs_rd->rd_tableam->scan_rescan(sscan, 0, NULL, false, false, false,
+ false);
sscan->rs_rd->rd_tableam->scan_set_tidrange(sscan, mintid, maxtid);
}
@@ -1123,7 +1125,9 @@ extern void table_parallelscan_initialize(Relation rel,
* Caller must hold a suitable lock on the relation.
*/
extern TableScanDesc table_beginscan_parallel(Relation relation,
- ParallelTableScanDesc pscan);
+ ParallelTableScanDesc pscan,
+ int nkeys,
+ struct ScanKeyData *key);
/*
* Restart a parallel scan. Call this in the leader process. Caller is
--
2.39.5
--7xovazs7fbn7xfcr
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v1-0002-Simple-quals-push-down-to-table-AMs.patch"