[PATCH 2/7] Pass the number of ScanKeys to scan_rescan()
Julien Tachoires <julien@tachoires.me>
From: Julien Tachoires <julien@tachoires.me>
To:
Date: 2025-12-02T09:40:55Z
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().
We also rename the variable "key" to "keys" in multiple places in
order to make clear that this is an array of ScanKeys.
---
src/backend/access/brin/brin.c | 3 +-
src/backend/access/gin/gininsert.c | 3 +-
src/backend/access/heap/heapam.c | 22 +++++++-----
src/backend/access/nbtree/nbtsort.c | 3 +-
src/backend/access/table/tableam.c | 9 ++---
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 | 7 ++--
src/include/access/tableam.h | 41 ++++++++++++-----------
12 files changed, 59 insertions(+), 44 deletions(-)
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index cb3331921cb..0a43f67f919 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -2842,7 +2842,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 f87c60a230c..9f7a55f3647 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -2058,7 +2058,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 1d9f9efa4fd..25bc941a815 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -346,10 +346,13 @@ bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data,
/* ----------------
* initscan - scan code common to heap_beginscan and heap_rescan
+ *
+ * Note: in order to pass on the ScanKeys to the scan, this function takes as
+ * arguments the number of ScanKeys and one array of ScanKeys.
* ----------------
*/
static void
-initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
+initscan(HeapScanDesc scan, int nkeys, ScanKey keys, bool keep_startblock)
{
ParallelBlockTableScanDesc bpscan = NULL;
bool allow_strat;
@@ -471,10 +474,13 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
/* page-at-a-time fields are always invalid when not rs_inited */
/*
- * copy the scan key, if appropriate
+ * copy the scan keys, if appropriate
*/
- if (key != NULL && scan->rs_base.rs_nkeys > 0)
- memcpy(scan->rs_base.rs_key, key, scan->rs_base.rs_nkeys * sizeof(ScanKeyData));
+ if (keys != NULL && nkeys > 0)
+ {
+ scan->rs_base.rs_nkeys = nkeys;
+ memcpy(scan->rs_base.rs_key, keys, nkeys * sizeof(ScanKeyData));
+ }
/*
* Currently, we only have a stats counter for sequential heap scans (but
@@ -1127,7 +1133,7 @@ continue_page:
TableScanDesc
heap_beginscan(Relation relation, Snapshot snapshot,
- int nkeys, ScanKey key,
+ int nkeys, ScanKey keys,
ParallelTableScanDesc parallel_scan,
uint32 flags)
{
@@ -1228,7 +1234,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
else
scan->rs_base.rs_key = NULL;
- initscan(scan, key, false);
+ initscan(scan, nkeys, keys, false);
scan->rs_read_stream = NULL;
@@ -1280,7 +1286,7 @@ heap_beginscan(Relation relation, Snapshot snapshot,
}
void
-heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
+heap_rescan(TableScanDesc sscan, int nkeys, ScanKey keys, bool set_params,
bool allow_strat, bool allow_sync, bool allow_pagemode)
{
HeapScanDesc scan = (HeapScanDesc) sscan;
@@ -1329,7 +1335,7 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
/*
* reinitialize scan descriptor
*/
- initscan(scan, key, true);
+ initscan(scan, nkeys, keys, true);
}
void
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 454adaee7dc..9c757a1ee95 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -1925,7 +1925,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 1e099febdc8..0efa564f7b2 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -110,14 +110,14 @@ table_slot_create(Relation relation, List **reglist)
*/
TableScanDesc
-table_beginscan_catalog(Relation relation, int nkeys, ScanKeyData *key)
+table_beginscan_catalog(Relation relation, int nkeys, ScanKeyData *keys)
{
uint32 flags = SO_TYPE_SEQSCAN |
SO_ALLOW_STRAT | SO_ALLOW_SYNC | SO_ALLOW_PAGEMODE | SO_TEMP_SNAPSHOT;
Oid relid = RelationGetRelid(relation);
Snapshot snapshot = RegisterSnapshot(GetCatalogSnapshot(relid));
- return relation->rd_tableam->scan_begin(relation, snapshot, nkeys, key,
+ return relation->rd_tableam->scan_begin(relation, snapshot, nkeys, keys,
NULL, flags);
}
@@ -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, ScanKeyData *keys)
{
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, keys,
pscan, flags);
}
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index def32774c90..b7d45daa55a 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..454d4ee0499 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 new 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 d50c6600358..0ab70d891c4 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -465,7 +465,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 632c4332a8c..7dd5e0bcd78 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -325,14 +325,15 @@ typedef struct PruneFreezeResult
extern TableScanDesc heap_beginscan(Relation relation, Snapshot snapshot,
- int nkeys, ScanKey key,
+ int nkeys, ScanKey keys,
ParallelTableScanDesc parallel_scan,
uint32 flags);
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 keys,
+ 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 2fa790b6bf5..848aa114de1 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -326,7 +326,7 @@ typedef struct TableAmRoutine
*/
TableScanDesc (*scan_begin) (Relation rel,
Snapshot snapshot,
- int nkeys, ScanKeyData *key,
+ int nkeys, ScanKeyData *keys,
ParallelTableScanDesc pscan,
uint32 flags);
@@ -340,9 +340,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, ScanKeyData *key,
- bool set_params, bool allow_strat,
- bool allow_sync, bool allow_pagemode);
+ void (*scan_rescan) (TableScanDesc scan, int nkeys,
+ ScanKeyData *keys, bool set_params,
+ bool allow_strat, bool allow_sync,
+ bool allow_pagemode);
/*
* Return next tuple from `scan`, store in slot.
@@ -874,12 +875,12 @@ extern TupleTableSlot *table_slot_create(Relation relation, List **reglist);
*/
static inline TableScanDesc
table_beginscan(Relation rel, Snapshot snapshot,
- int nkeys, ScanKeyData *key)
+ int nkeys, ScanKeyData *keys)
{
uint32 flags = SO_TYPE_SEQSCAN |
SO_ALLOW_STRAT | SO_ALLOW_SYNC | SO_ALLOW_PAGEMODE;
- return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+ return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, keys, NULL, flags);
}
/*
@@ -887,7 +888,7 @@ table_beginscan(Relation rel, Snapshot snapshot,
* snapshot appropriate for scanning catalog relations.
*/
extern TableScanDesc table_beginscan_catalog(Relation relation, int nkeys,
- ScanKeyData *key);
+ ScanKeyData *keys);
/*
* Like table_beginscan(), but table_beginscan_strat() offers an extended API
@@ -898,7 +899,7 @@ extern TableScanDesc table_beginscan_catalog(Relation relation, int nkeys,
*/
static inline TableScanDesc
table_beginscan_strat(Relation rel, Snapshot snapshot,
- int nkeys, ScanKeyData *key,
+ int nkeys, ScanKeyData *keys,
bool allow_strat, bool allow_sync)
{
uint32 flags = SO_TYPE_SEQSCAN | SO_ALLOW_PAGEMODE;
@@ -908,7 +909,7 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
if (allow_sync)
flags |= SO_ALLOW_SYNC;
- return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+ return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, keys, NULL, flags);
}
/*
@@ -919,11 +920,11 @@ table_beginscan_strat(Relation rel, Snapshot snapshot,
*/
static inline TableScanDesc
table_beginscan_bm(Relation rel, Snapshot snapshot,
- int nkeys, ScanKeyData *key)
+ int nkeys, ScanKeyData *keys)
{
uint32 flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
- return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key,
+ return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, keys,
NULL, flags);
}
@@ -936,7 +937,7 @@ table_beginscan_bm(Relation rel, Snapshot snapshot,
*/
static inline TableScanDesc
table_beginscan_sampling(Relation rel, Snapshot snapshot,
- int nkeys, ScanKeyData *key,
+ int nkeys, ScanKeyData *keys,
bool allow_strat, bool allow_sync,
bool allow_pagemode)
{
@@ -949,7 +950,7 @@ table_beginscan_sampling(Relation rel, Snapshot snapshot,
if (allow_pagemode)
flags |= SO_ALLOW_PAGEMODE;
- return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+ return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, keys, NULL, flags);
}
/*
@@ -991,9 +992,9 @@ table_endscan(TableScanDesc scan)
* Restart a relation scan.
*/
static inline void
-table_rescan(TableScanDesc scan, ScanKeyData *key)
+table_rescan(TableScanDesc scan, int nkeys, ScanKeyData *keys)
{
- scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
+ scan->rs_rd->rd_tableam->scan_rescan(scan, nkeys, keys, false, false, false, false);
}
/*
@@ -1005,10 +1006,10 @@ table_rescan(TableScanDesc scan, ScanKeyData *key)
* previously selected startblock will be kept.
*/
static inline void
-table_rescan_set_params(TableScanDesc scan, ScanKeyData *key,
+table_rescan_set_params(TableScanDesc scan, int nkeys, ScanKeyData *keys,
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, keys, true,
allow_strat, allow_sync,
allow_pagemode);
}
@@ -1073,7 +1074,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);
}
@@ -1128,7 +1130,8 @@ 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, ScanKeyData *keys);
/*
* Begin a parallel tid range scan. `pscan` needs to have been initialized
--
2.39.5
--lqhr7owlpsibhw3z
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0003-Simple-quals-push-down-to-table-AMs.patch"