Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f9bc34f

Browse files
committed
Further refactor of heapgettup and heapgettup_pagemode
Backward and forward scans share much of the same page acquisition code. Here we consolidate that code to reduce some duplication. Additionally, add a new rs_coffset field to HeapScanDescData to track the offset of the current tuple. The new field fits nicely into the padding between a bool and BlockNumber field and saves having to look at the last returned tuple to figure out which offset we should be looking at for the current tuple. Author: Melanie Plageman Reviewed-by: David Rowley Discussion: https://postgr.es/m/CAAKRu_bvkhka0CZQun28KTqhuUh5ZqY=_T8QEqZqOL02rpi2bw@mail.gmail.com
1 parent cdf6518 commit f9bc34f

File tree

2 files changed

+63
-138
lines changed

2 files changed

+63
-138
lines changed

src/backend/access/heap/heapam.c

+62-138
Original file line numberDiff line numberDiff line change
@@ -576,101 +576,67 @@ heapgettup(HeapScanDesc scan,
576576
BlockNumber block;
577577
bool finished;
578578
Page page;
579-
int lines;
580579
OffsetNumber lineoff;
581580
int linesleft;
582581
ItemId lpp;
583582

584-
/*
585-
* calculate next starting lineoff, given scan direction
586-
*/
587-
if (ScanDirectionIsForward(dir))
583+
if (unlikely(!scan->rs_inited))
588584
{
589-
if (!scan->rs_inited)
590-
{
591-
block = heapgettup_initial_block(scan, dir);
585+
block = heapgettup_initial_block(scan, dir);
592586

593-
/*
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
597-
*/
598-
if (block == InvalidBlockNumber)
599-
{
600-
Assert(!BufferIsValid(scan->rs_cbuf));
601-
tuple->t_data = NULL;
602-
return;
603-
}
604-
heapgetpage((TableScanDesc) scan, block);
605-
lineoff = FirstOffsetNumber; /* first offnum */
606-
scan->rs_inited = true;
607-
}
608-
else
587+
/*
588+
* Check if we have reached the end of the scan already. This could
589+
* happen if the table is empty or if the parallel workers have
590+
* already finished the scan before we did anything ourselves
591+
*/
592+
if (block == InvalidBlockNumber)
609593
{
610-
/* continue from previously returned page/tuple */
611-
block = scan->rs_cblock; /* current page */
612-
lineoff = /* next offnum */
613-
OffsetNumberNext(ItemPointerGetOffsetNumber(&(tuple->t_self)));
594+
Assert(!BufferIsValid(scan->rs_cbuf));
595+
tuple->t_data = NULL;
596+
return;
614597
}
615598

616-
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
599+
heapgetpage((TableScanDesc) scan, block);
617600

601+
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
618602
page = BufferGetPage(scan->rs_cbuf);
619603
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
620-
lines = PageGetMaxOffsetNumber(page);
621-
/* block and lineoff now reference the physically next tid */
622604

623-
linesleft = lines - lineoff + 1;
605+
linesleft = PageGetMaxOffsetNumber(page) - FirstOffsetNumber + 1;
606+
607+
if (ScanDirectionIsForward(dir))
608+
lineoff = FirstOffsetNumber; /* first offnum */
609+
else
610+
lineoff = (OffsetNumber) linesleft;
611+
612+
scan->rs_inited = true;
624613
}
625614
else
626615
{
627-
if (!scan->rs_inited)
628-
{
629-
block = heapgettup_initial_block(scan, dir);
630-
631-
/*
632-
* Check if we have reached the end of the scan already. This
633-
* could happen if the table is empty.
634-
*/
635-
if (block == InvalidBlockNumber)
636-
{
637-
Assert(!BufferIsValid(scan->rs_cbuf));
638-
tuple->t_data = NULL;
639-
return;
640-
}
616+
/* continue from previously returned page/tuple */
617+
block = scan->rs_cblock;
641618

642-
heapgetpage((TableScanDesc) scan, block);
643-
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
619+
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
620+
page = BufferGetPage(scan->rs_cbuf);
621+
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
644622

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;
623+
if (ScanDirectionIsForward(dir))
624+
{
625+
lineoff = OffsetNumberNext(scan->rs_coffset);
626+
linesleft = PageGetMaxOffsetNumber(page) - lineoff + 1;
650627
}
651628
else
652629
{
653-
/* continue from previously returned page/tuple */
654-
block = scan->rs_cblock; /* current page */
655-
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
656-
657-
page = BufferGetPage(scan->rs_cbuf);
658-
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
659-
lines = PageGetMaxOffsetNumber(page);
660-
661630
/*
662631
* The previous returned tuple may have been vacuumed since the
663632
* previous scan when we use a non-MVCC snapshot, so we must
664633
* re-establish the lineoff <= PageGetMaxOffsetNumber(page)
665634
* invariant
666635
*/
667-
lineoff = /* previous offnum */
668-
Min(lines,
669-
OffsetNumberPrev(ItemPointerGetOffsetNumber(&(tuple->t_self))));
636+
lineoff = Min(PageGetMaxOffsetNumber(page),
637+
OffsetNumberPrev(scan->rs_coffset));
638+
linesleft = lineoff;
670639
}
671-
/* block and lineoff now reference the physically previous tid */
672-
673-
linesleft = lineoff;
674640
}
675641

676642
/*
@@ -715,6 +681,7 @@ heapgettup(HeapScanDesc scan,
715681
if (valid)
716682
{
717683
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
684+
scan->rs_coffset = lineoff;
718685
return;
719686
}
720687
}
@@ -807,12 +774,11 @@ heapgettup(HeapScanDesc scan,
807774

808775
page = BufferGetPage(scan->rs_cbuf);
809776
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
810-
lines = PageGetMaxOffsetNumber(page);
811-
linesleft = lines;
777+
linesleft = PageGetMaxOffsetNumber(page);
812778
if (backward)
813779
{
814-
lineoff = lines;
815-
lpp = PageGetItemId(page, lines);
780+
lineoff = linesleft;
781+
lpp = PageGetItemId(page, linesleft);
816782
}
817783
else
818784
{
@@ -846,87 +812,46 @@ heapgettup_pagemode(HeapScanDesc scan,
846812
BlockNumber block;
847813
bool finished;
848814
Page page;
849-
int lines;
850815
int lineindex;
851816
OffsetNumber lineoff;
852817
int linesleft;
853818
ItemId lpp;
854819

855-
/*
856-
* calculate next starting lineindex, given scan direction
857-
*/
858-
if (ScanDirectionIsForward(dir))
820+
if (unlikely(!scan->rs_inited))
859821
{
860-
if (!scan->rs_inited)
861-
{
862-
block = heapgettup_initial_block(scan, dir);
822+
block = heapgettup_initial_block(scan, dir);
863823

864-
/*
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
868-
*/
869-
if (block == InvalidBlockNumber)
870-
{
871-
Assert(!BufferIsValid(scan->rs_cbuf));
872-
tuple->t_data = NULL;
873-
return;
874-
}
875-
heapgetpage((TableScanDesc) scan, block);
876-
lineindex = 0;
877-
scan->rs_inited = true;
878-
}
879-
else
824+
/*
825+
* Check if we have reached the end of the scan already. This could
826+
* happen if the table is empty or if the other workers in a parallel
827+
* scan have already finished the scan.
828+
*/
829+
if (block == InvalidBlockNumber)
880830
{
881-
/* continue from previously returned page/tuple */
882-
block = scan->rs_cblock; /* current page */
883-
lineindex = scan->rs_cindex + 1;
831+
Assert(!BufferIsValid(scan->rs_cbuf));
832+
tuple->t_data = NULL;
833+
return;
884834
}
885835

836+
heapgetpage((TableScanDesc) scan, block);
886837
page = BufferGetPage(scan->rs_cbuf);
887838
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
888-
lines = scan->rs_ntuples;
889-
/* block and lineindex now reference the next visible tid */
890-
891-
linesleft = lines - lineindex;
839+
linesleft = scan->rs_ntuples;
840+
lineindex = ScanDirectionIsForward(dir) ? 0 : linesleft - 1;
841+
scan->rs_inited = true;
892842
}
893843
else
894844
{
895-
if (!scan->rs_inited)
896-
{
897-
block = heapgettup_initial_block(scan, dir);
898-
899-
/*
900-
* Check if we have reached the end of the scan already. This
901-
* could happen if the table is empty.
902-
*/
903-
if (block == InvalidBlockNumber)
904-
{
905-
Assert(!BufferIsValid(scan->rs_cbuf));
906-
tuple->t_data = NULL;
907-
return;
908-
}
845+
/* continue from previously returned page/tuple */
846+
block = scan->rs_cblock; /* current page */
847+
page = BufferGetPage(scan->rs_cbuf);
848+
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
909849

910-
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;
916-
}
850+
lineindex = scan->rs_cindex + dir;
851+
if (ScanDirectionIsForward(dir))
852+
linesleft = scan->rs_ntuples - lineindex;
917853
else
918-
{
919-
/* continue from previously returned page/tuple */
920-
block = scan->rs_cblock; /* current page */
921-
922-
page = BufferGetPage(scan->rs_cbuf);
923-
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
924-
lines = scan->rs_ntuples;
925-
lineindex = scan->rs_cindex - 1;
926-
}
927-
/* block and lineindex now reference the previous visible tid */
928-
929-
linesleft = lineindex + 1;
854+
linesleft = scan->rs_cindex;
930855
}
931856

932857
/*
@@ -1041,10 +966,9 @@ heapgettup_pagemode(HeapScanDesc scan,
1041966

1042967
page = BufferGetPage(scan->rs_cbuf);
1043968
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
1044-
lines = scan->rs_ntuples;
1045-
linesleft = lines;
969+
linesleft = scan->rs_ntuples;
1046970
if (backward)
1047-
lineindex = lines - 1;
971+
lineindex = linesleft - 1;
1048972
else
1049973
lineindex = 0;
1050974
}

src/include/access/heapam.h

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ typedef struct HeapScanDescData
5757

5858
/* scan current state */
5959
bool rs_inited; /* false = scan not init'd yet */
60+
OffsetNumber rs_coffset; /* current offset # in non-page-at-a-time mode */
6061
BlockNumber rs_cblock; /* current block # in scan, if any */
6162
Buffer rs_cbuf; /* current buffer in scan, if any */
6263
/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */

0 commit comments

Comments
 (0)