Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fb1a59d

Browse filesBrowse files
committed
Refactor heapam.c adding heapgettup_initial_block function
Here we adjust heapgettup() and heapgettup_pagemode() to move the code that fetches the first block number to scan out into a helper function. This removes some code duplication. Author: Melanie Plageman Reviewed-by: David Rowley Discussion: https://postgr.es/m/CAAKRu_bvkhka0CZQun28KTqhuUh5ZqY=_T8QEqZqOL02rpi2bw@mail.gmail.com
1 parent 253432f commit fb1a59d
Copy full SHA for fb1a59d

File tree

1 file changed

+102
-121
lines changed
Filter options

1 file changed

+102
-121
lines changed

‎src/backend/access/heap/heapam.c

Copy file name to clipboardExpand all lines: src/backend/access/heap/heapam.c
+102-121Lines changed: 102 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,67 @@ heapgetpage(TableScanDesc sscan, BlockNumber block)
483483
scan->rs_ntuples = ntup;
484484
}
485485

486+
/*
487+
* heapgettup_initial_block - return the first BlockNumber to scan
488+
*
489+
* Returns InvalidBlockNumber when there are no blocks to scan. This can
490+
* occur with empty tables and in parallel scans when parallel workers get all
491+
* of the pages before we can get a chance to get our first page.
492+
*/
493+
static BlockNumber
494+
heapgettup_initial_block(HeapScanDesc scan, ScanDirection dir)
495+
{
496+
Assert(!scan->rs_inited);
497+
498+
/* When there are no pages to scan, return InvalidBlockNumber */
499+
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
500+
return InvalidBlockNumber;
501+
502+
if (ScanDirectionIsForward(dir))
503+
{
504+
/* serial scan */
505+
if (scan->rs_base.rs_parallel == NULL)
506+
return scan->rs_startblock;
507+
else
508+
{
509+
/* parallel scan */
510+
table_block_parallelscan_startblock_init(scan->rs_base.rs_rd,
511+
scan->rs_parallelworkerdata,
512+
(ParallelBlockTableScanDesc) scan->rs_base.rs_parallel);
513+
514+
/* may return InvalidBlockNumber if there are no more blocks */
515+
return table_block_parallelscan_nextpage(scan->rs_base.rs_rd,
516+
scan->rs_parallelworkerdata,
517+
(ParallelBlockTableScanDesc) scan->rs_base.rs_parallel);
518+
}
519+
}
520+
else
521+
{
522+
/* backward parallel scan not supported */
523+
Assert(scan->rs_base.rs_parallel == NULL);
524+
525+
/*
526+
* Disable reporting to syncscan logic in a backwards scan; it's not
527+
* very likely anyone else is doing the same thing at the same time,
528+
* and much more likely that we'll just bollix things for forward
529+
* scanners.
530+
*/
531+
scan->rs_base.rs_flags &= ~SO_ALLOW_SYNC;
532+
533+
/*
534+
* Start from last page of the scan. Ensure we take into account
535+
* rs_numblocks if it's been adjusted by heap_setscanlimits().
536+
*/
537+
if (scan->rs_numblocks != InvalidBlockNumber)
538+
return (scan->rs_startblock + scan->rs_numblocks - 1) % scan->rs_nblocks;
539+
540+
if (scan->rs_startblock > 0)
541+
return scan->rs_startblock - 1;
542+
543+
return scan->rs_nblocks - 1;
544+
}
545+
}
546+
486547
/* ----------------
487548
* heapgettup - fetch next heap tuple
488549
*
@@ -527,38 +588,19 @@ heapgettup(HeapScanDesc scan,
527588
{
528589
if (!scan->rs_inited)
529590
{
591+
block = heapgettup_initial_block(scan, dir);
592+
530593
/*
531-
* return null immediately if relation is empty
594+
* Check if we have reached the end of the scan already. This
595+
* could happen if the table is empty or if the parallel workers
596+
* have already finished the scan before we did anything ourselves
532597
*/
533-
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
598+
if (block == InvalidBlockNumber)
534599
{
535600
Assert(!BufferIsValid(scan->rs_cbuf));
536601
tuple->t_data = NULL;
537602
return;
538603
}
539-
if (scan->rs_base.rs_parallel != NULL)
540-
{
541-
ParallelBlockTableScanDesc pbscan =
542-
(ParallelBlockTableScanDesc) scan->rs_base.rs_parallel;
543-
ParallelBlockTableScanWorker pbscanwork =
544-
scan->rs_parallelworkerdata;
545-
546-
table_block_parallelscan_startblock_init(scan->rs_base.rs_rd,
547-
pbscanwork, pbscan);
548-
549-
block = table_block_parallelscan_nextpage(scan->rs_base.rs_rd,
550-
pbscanwork, pbscan);
551-
552-
/* Other processes might have already finished the scan. */
553-
if (block == InvalidBlockNumber)
554-
{
555-
Assert(!BufferIsValid(scan->rs_cbuf));
556-
tuple->t_data = NULL;
557-
return;
558-
}
559-
}
560-
else
561-
block = scan->rs_startblock; /* first page */
562604
heapgetpage((TableScanDesc) scan, block);
563605
lineoff = FirstOffsetNumber; /* first offnum */
564606
scan->rs_inited = true;
@@ -582,60 +624,40 @@ heapgettup(HeapScanDesc scan,
582624
}
583625
else
584626
{
585-
/* backward parallel scan not supported */
586-
Assert(scan->rs_base.rs_parallel == NULL);
587-
588627
if (!scan->rs_inited)
589628
{
629+
block = heapgettup_initial_block(scan, dir);
630+
590631
/*
591-
* return null immediately if relation is empty
632+
* Check if we have reached the end of the scan already. This
633+
* could happen if the table is empty.
592634
*/
593-
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
635+
if (block == InvalidBlockNumber)
594636
{
595637
Assert(!BufferIsValid(scan->rs_cbuf));
596638
tuple->t_data = NULL;
597639
return;
598640
}
599641

600-
/*
601-
* Disable reporting to syncscan logic in a backwards scan; it's
602-
* not very likely anyone else is doing the same thing at the same
603-
* time, and much more likely that we'll just bollix things for
604-
* forward scanners.
605-
*/
606-
scan->rs_base.rs_flags &= ~SO_ALLOW_SYNC;
607-
608-
/*
609-
* Start from last page of the scan. Ensure we take into account
610-
* rs_numblocks if it's been adjusted by heap_setscanlimits().
611-
*/
612-
if (scan->rs_numblocks != InvalidBlockNumber)
613-
block = (scan->rs_startblock + scan->rs_numblocks - 1) % scan->rs_nblocks;
614-
else if (scan->rs_startblock > 0)
615-
block = scan->rs_startblock - 1;
616-
else
617-
block = scan->rs_nblocks - 1;
618642
heapgetpage((TableScanDesc) scan, block);
643+
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
644+
645+
page = BufferGetPage(scan->rs_cbuf);
646+
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
647+
lines = PageGetMaxOffsetNumber(page);
648+
lineoff = lines; /* final offnum */
649+
scan->rs_inited = true;
619650
}
620651
else
621652
{
622653
/* continue from previously returned page/tuple */
623654
block = scan->rs_cblock; /* current page */
624-
}
655+
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
625656

626-
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
657+
page = BufferGetPage(scan->rs_cbuf);
658+
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
659+
lines = PageGetMaxOffsetNumber(page);
627660

628-
page = BufferGetPage(scan->rs_cbuf);
629-
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
630-
lines = PageGetMaxOffsetNumber(page);
631-
632-
if (!scan->rs_inited)
633-
{
634-
lineoff = lines; /* final offnum */
635-
scan->rs_inited = true;
636-
}
637-
else
638-
{
639661
/*
640662
* The previous returned tuple may have been vacuumed since the
641663
* previous scan when we use a non-MVCC snapshot, so we must
@@ -837,38 +859,19 @@ heapgettup_pagemode(HeapScanDesc scan,
837859
{
838860
if (!scan->rs_inited)
839861
{
862+
block = heapgettup_initial_block(scan, dir);
863+
840864
/*
841-
* return null immediately if relation is empty
865+
* Check if we have reached the end of the scan already. This
866+
* could happen if the table is empty or if the parallel workers
867+
* have already finished the scan before we did anything ourselves
842868
*/
843-
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
869+
if (block == InvalidBlockNumber)
844870
{
845871
Assert(!BufferIsValid(scan->rs_cbuf));
846872
tuple->t_data = NULL;
847873
return;
848874
}
849-
if (scan->rs_base.rs_parallel != NULL)
850-
{
851-
ParallelBlockTableScanDesc pbscan =
852-
(ParallelBlockTableScanDesc) scan->rs_base.rs_parallel;
853-
ParallelBlockTableScanWorker pbscanwork =
854-
scan->rs_parallelworkerdata;
855-
856-
table_block_parallelscan_startblock_init(scan->rs_base.rs_rd,
857-
pbscanwork, pbscan);
858-
859-
block = table_block_parallelscan_nextpage(scan->rs_base.rs_rd,
860-
pbscanwork, pbscan);
861-
862-
/* Other processes might have already finished the scan. */
863-
if (block == InvalidBlockNumber)
864-
{
865-
Assert(!BufferIsValid(scan->rs_cbuf));
866-
tuple->t_data = NULL;
867-
return;
868-
}
869-
}
870-
else
871-
block = scan->rs_startblock; /* first page */
872875
heapgetpage((TableScanDesc) scan, block);
873876
lineindex = 0;
874877
scan->rs_inited = true;
@@ -889,58 +892,36 @@ heapgettup_pagemode(HeapScanDesc scan,
889892
}
890893
else
891894
{
892-
/* backward parallel scan not supported */
893-
Assert(scan->rs_base.rs_parallel == NULL);
894-
895895
if (!scan->rs_inited)
896896
{
897+
block = heapgettup_initial_block(scan, dir);
898+
897899
/*
898-
* return null immediately if relation is empty
900+
* Check if we have reached the end of the scan already. This
901+
* could happen if the table is empty.
899902
*/
900-
if (scan->rs_nblocks == 0 || scan->rs_numblocks == 0)
903+
if (block == InvalidBlockNumber)
901904
{
902905
Assert(!BufferIsValid(scan->rs_cbuf));
903906
tuple->t_data = NULL;
904907
return;
905908
}
906909

907-
/*
908-
* Disable reporting to syncscan logic in a backwards scan; it's
909-
* not very likely anyone else is doing the same thing at the same
910-
* time, and much more likely that we'll just bollix things for
911-
* forward scanners.
912-
*/
913-
scan->rs_base.rs_flags &= ~SO_ALLOW_SYNC;
914-
915-
/*
916-
* Start from last page of the scan. Ensure we take into account
917-
* rs_numblocks if it's been adjusted by heap_setscanlimits().
918-
*/
919-
if (scan->rs_numblocks != InvalidBlockNumber)
920-
block = (scan->rs_startblock + scan->rs_numblocks - 1) % scan->rs_nblocks;
921-
else if (scan->rs_startblock > 0)
922-
block = scan->rs_startblock - 1;
923-
else
924-
block = scan->rs_nblocks - 1;
925910
heapgetpage((TableScanDesc) scan, block);
911+
page = BufferGetPage(scan->rs_cbuf);
912+
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
913+
lines = scan->rs_ntuples;
914+
lineindex = lines - 1;
915+
scan->rs_inited = true;
926916
}
927917
else
928918
{
929919
/* continue from previously returned page/tuple */
930920
block = scan->rs_cblock; /* current page */
931-
}
932-
933-
page = BufferGetPage(scan->rs_cbuf);
934-
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
935-
lines = scan->rs_ntuples;
936921

937-
if (!scan->rs_inited)
938-
{
939-
lineindex = lines - 1;
940-
scan->rs_inited = true;
941-
}
942-
else
943-
{
922+
page = BufferGetPage(scan->rs_cbuf);
923+
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
924+
lines = scan->rs_ntuples;
944925
lineindex = scan->rs_cindex - 1;
945926
}
946927
/* block and lineindex now reference the previous visible tid */

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.