mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
Fix some oversights in BRIN patch.
Remove HeapScanDescData.rs_initblock, which wasn't being used for anything in the final version of the patch. Fix IndexBuildHeapScan so that it supports syncscan again; the patch broke synchronous scanning for index builds by forcing rs_startblk to zero even when the caller did not care about that and had asked for syncscan. Add some commentary and usage defenses to heap_setscanlimits(). Fix heapam so that asking for rs_numblocks == 0 does what you would reasonably expect. As coded it amounted to requesting a whole-table scan, because those "--x <= 0" tests on an unsigned variable would behave surprisingly.
This commit is contained in:
parent
29f171c81a
commit
35ac618a7c
@ -277,7 +277,6 @@ initscan(HeapScanDesc scan, ScanKey key, bool is_rescan)
|
|||||||
scan->rs_startblock = 0;
|
scan->rs_startblock = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
scan->rs_initblock = 0;
|
|
||||||
scan->rs_numblocks = InvalidBlockNumber;
|
scan->rs_numblocks = InvalidBlockNumber;
|
||||||
scan->rs_inited = false;
|
scan->rs_inited = false;
|
||||||
scan->rs_ctup.t_data = NULL;
|
scan->rs_ctup.t_data = NULL;
|
||||||
@ -302,11 +301,22 @@ initscan(HeapScanDesc scan, ScanKey key, bool is_rescan)
|
|||||||
pgstat_count_heap_scan(scan->rs_rd);
|
pgstat_count_heap_scan(scan->rs_rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
void
|
||||||
heap_setscanlimits(HeapScanDesc scan, BlockNumber startBlk, BlockNumber numBlks)
|
heap_setscanlimits(HeapScanDesc scan, BlockNumber startBlk, BlockNumber numBlks)
|
||||||
{
|
{
|
||||||
|
Assert(!scan->rs_inited); /* else too late to change */
|
||||||
|
Assert(!scan->rs_syncscan); /* else rs_startblock is significant */
|
||||||
|
|
||||||
|
/* Check startBlk is valid (but allow case of zero blocks...) */
|
||||||
|
Assert(startBlk == 0 || startBlk < scan->rs_nblocks);
|
||||||
|
|
||||||
scan->rs_startblock = startBlk;
|
scan->rs_startblock = startBlk;
|
||||||
scan->rs_initblock = startBlk;
|
|
||||||
scan->rs_numblocks = numBlks;
|
scan->rs_numblocks = numBlks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +487,7 @@ heapgettup(HeapScanDesc scan,
|
|||||||
/*
|
/*
|
||||||
* return null immediately if relation is empty
|
* return null immediately if relation is empty
|
||||||
*/
|
*/
|
||||||
if (scan->rs_nblocks == 0)
|
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
|
||||||
{
|
{
|
||||||
Assert(!BufferIsValid(scan->rs_cbuf));
|
Assert(!BufferIsValid(scan->rs_cbuf));
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
@ -511,7 +521,7 @@ heapgettup(HeapScanDesc scan,
|
|||||||
/*
|
/*
|
||||||
* return null immediately if relation is empty
|
* return null immediately if relation is empty
|
||||||
*/
|
*/
|
||||||
if (scan->rs_nblocks == 0)
|
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
|
||||||
{
|
{
|
||||||
Assert(!BufferIsValid(scan->rs_cbuf));
|
Assert(!BufferIsValid(scan->rs_cbuf));
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
@ -651,7 +661,7 @@ heapgettup(HeapScanDesc scan,
|
|||||||
if (backward)
|
if (backward)
|
||||||
{
|
{
|
||||||
finished = (page == scan->rs_startblock) ||
|
finished = (page == scan->rs_startblock) ||
|
||||||
(scan->rs_numblocks != InvalidBlockNumber ? --scan->rs_numblocks <= 0 : false);
|
(scan->rs_numblocks != InvalidBlockNumber ? --scan->rs_numblocks == 0 : false);
|
||||||
if (page == 0)
|
if (page == 0)
|
||||||
page = scan->rs_nblocks;
|
page = scan->rs_nblocks;
|
||||||
page--;
|
page--;
|
||||||
@ -662,7 +672,7 @@ heapgettup(HeapScanDesc scan,
|
|||||||
if (page >= scan->rs_nblocks)
|
if (page >= scan->rs_nblocks)
|
||||||
page = 0;
|
page = 0;
|
||||||
finished = (page == scan->rs_startblock) ||
|
finished = (page == scan->rs_startblock) ||
|
||||||
(scan->rs_numblocks != InvalidBlockNumber ? --scan->rs_numblocks <= 0 : false);
|
(scan->rs_numblocks != InvalidBlockNumber ? --scan->rs_numblocks == 0 : false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Report our new scan position for synchronization purposes. We
|
* Report our new scan position for synchronization purposes. We
|
||||||
@ -754,7 +764,7 @@ heapgettup_pagemode(HeapScanDesc scan,
|
|||||||
/*
|
/*
|
||||||
* return null immediately if relation is empty
|
* return null immediately if relation is empty
|
||||||
*/
|
*/
|
||||||
if (scan->rs_nblocks == 0)
|
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
|
||||||
{
|
{
|
||||||
Assert(!BufferIsValid(scan->rs_cbuf));
|
Assert(!BufferIsValid(scan->rs_cbuf));
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
@ -785,7 +795,7 @@ heapgettup_pagemode(HeapScanDesc scan,
|
|||||||
/*
|
/*
|
||||||
* return null immediately if relation is empty
|
* return null immediately if relation is empty
|
||||||
*/
|
*/
|
||||||
if (scan->rs_nblocks == 0)
|
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
|
||||||
{
|
{
|
||||||
Assert(!BufferIsValid(scan->rs_cbuf));
|
Assert(!BufferIsValid(scan->rs_cbuf));
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
@ -914,7 +924,7 @@ heapgettup_pagemode(HeapScanDesc scan,
|
|||||||
if (backward)
|
if (backward)
|
||||||
{
|
{
|
||||||
finished = (page == scan->rs_startblock) ||
|
finished = (page == scan->rs_startblock) ||
|
||||||
(scan->rs_numblocks != InvalidBlockNumber ? --scan->rs_numblocks <= 0 : false);
|
(scan->rs_numblocks != InvalidBlockNumber ? --scan->rs_numblocks == 0 : false);
|
||||||
if (page == 0)
|
if (page == 0)
|
||||||
page = scan->rs_nblocks;
|
page = scan->rs_nblocks;
|
||||||
page--;
|
page--;
|
||||||
@ -925,7 +935,7 @@ heapgettup_pagemode(HeapScanDesc scan,
|
|||||||
if (page >= scan->rs_nblocks)
|
if (page >= scan->rs_nblocks)
|
||||||
page = 0;
|
page = 0;
|
||||||
finished = (page == scan->rs_startblock) ||
|
finished = (page == scan->rs_startblock) ||
|
||||||
(scan->rs_numblocks != InvalidBlockNumber ? --scan->rs_numblocks <= 0 : false);
|
(scan->rs_numblocks != InvalidBlockNumber ? --scan->rs_numblocks == 0 : false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Report our new scan position for synchronization purposes. We
|
* Report our new scan position for synchronization purposes. We
|
||||||
|
@ -2168,7 +2168,8 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
/*
|
/*
|
||||||
* As above, except that instead of scanning the complete heap, only the given
|
* As above, except that instead of scanning the complete heap, only the given
|
||||||
* number of blocks are scanned. Scan to end-of-rel can be signalled by
|
* number of blocks are scanned. Scan to end-of-rel can be signalled by
|
||||||
* passing InvalidBlockNumber as numblocks.
|
* passing InvalidBlockNumber as numblocks. Note that restricting the range
|
||||||
|
* to scan cannot be done when requesting syncscan.
|
||||||
*/
|
*/
|
||||||
double
|
double
|
||||||
IndexBuildHeapRangeScan(Relation heapRelation,
|
IndexBuildHeapRangeScan(Relation heapRelation,
|
||||||
@ -2251,7 +2252,14 @@ IndexBuildHeapRangeScan(Relation heapRelation,
|
|||||||
allow_sync); /* syncscan OK? */
|
allow_sync); /* syncscan OK? */
|
||||||
|
|
||||||
/* set our scan endpoints */
|
/* set our scan endpoints */
|
||||||
|
if (!allow_sync)
|
||||||
heap_setscanlimits(scan, start_blockno, numblocks);
|
heap_setscanlimits(scan, start_blockno, numblocks);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* syncscan can only be requested on whole relation */
|
||||||
|
Assert(start_blockno == 0);
|
||||||
|
Assert(numblocks == InvalidBlockNumber);
|
||||||
|
}
|
||||||
|
|
||||||
reltuples = 0;
|
reltuples = 0;
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ typedef struct HeapScanDescData
|
|||||||
/* state set up at initscan time */
|
/* state set up at initscan time */
|
||||||
BlockNumber rs_nblocks; /* total number of blocks in rel */
|
BlockNumber rs_nblocks; /* total number of blocks in rel */
|
||||||
BlockNumber rs_startblock; /* block # to start at */
|
BlockNumber rs_startblock; /* block # to start at */
|
||||||
BlockNumber rs_initblock; /* block # to consider initial of rel */
|
BlockNumber rs_numblocks; /* max number of blocks to scan */
|
||||||
BlockNumber rs_numblocks; /* number of blocks to scan */
|
/* rs_numblocks is usually InvalidBlockNumber, meaning "scan whole rel" */
|
||||||
BufferAccessStrategy rs_strategy; /* access strategy for reads */
|
BufferAccessStrategy rs_strategy; /* access strategy for reads */
|
||||||
bool rs_syncscan; /* report location to syncscan logic? */
|
bool rs_syncscan; /* report location to syncscan logic? */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user