Thread

  1. [PATCH 1/6] Pass the number of ScanKeys to scan_rescan()

    Julien Tachoires <julien@tachoires.me> — 2025-08-25T15:01:57Z

    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"