Skip to content

Commit cfcf56f

Browse files
committed
More refactoring of heapgettup() and heapgettup_pagemode()
Here we further simplify the code in heapgettup() and heapgettup_pagemode() to make better use of the helper functions added in the previous recent refactors in this area. In passing, remove an unneeded cast added in 8ca6d49. Author: Melanie Plageman Reviewed-by: Andres Freund, David Rowley Discussion: https://postgr.es/m/CAAKRu_YSOnhKsDyFcqJsKtBSrd32DP-jjXmv7hL0BPD-z0TGXQ@mail.gmail.com
1 parent 9ba37b2 commit cfcf56f

File tree

1 file changed

+78
-169
lines changed

1 file changed

+78
-169
lines changed

src/backend/access/heap/heapam.c

Lines changed: 78 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ heapgettup_start_page(HeapScanDesc scan, ScanDirection dir, int *linesleft,
567567

568568
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
569569

570-
*linesleft = PageGetMaxOffsetNumber((Page) page) - FirstOffsetNumber + 1;
570+
*linesleft = PageGetMaxOffsetNumber(page) - FirstOffsetNumber + 1;
571571

572572
if (ScanDirectionIsForward(dir))
573573
*lineoff = FirstOffsetNumber;
@@ -732,34 +732,17 @@ heapgettup(HeapScanDesc scan,
732732
ScanKey key)
733733
{
734734
HeapTuple tuple = &(scan->rs_ctup);
735-
bool backward = ScanDirectionIsBackward(dir);
736735
BlockNumber block;
737736
Page page;
738737
OffsetNumber lineoff;
739738
int linesleft;
740-
ItemId lpp;
741739

742740
if (unlikely(!scan->rs_inited))
743741
{
744742
block = heapgettup_initial_block(scan, dir);
745-
746-
/*
747-
* Check if we have reached the end of the scan already. This could
748-
* happen if the table is empty or if the parallel workers have
749-
* already finished the scan before we did anything ourselves
750-
*/
751-
if (block == InvalidBlockNumber)
752-
{
753-
Assert(!BufferIsValid(scan->rs_cbuf));
754-
tuple->t_data = NULL;
755-
return;
756-
}
743+
/* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
744+
Assert(block != InvalidBlockNumber || !BufferIsValid(scan->rs_cbuf));
757745
scan->rs_inited = true;
758-
759-
heapgetpage((TableScanDesc) scan, block);
760-
761-
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
762-
page = heapgettup_start_page(scan, dir, &linesleft, &lineoff);
763746
}
764747
else
765748
{
@@ -768,69 +751,60 @@ heapgettup(HeapScanDesc scan,
768751

769752
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
770753
page = heapgettup_continue_page(scan, dir, &linesleft, &lineoff);
754+
goto continue_page;
771755
}
772756

773757
/*
774758
* advance the scan until we find a qualifying tuple or run out of stuff
775759
* to scan
776760
*/
777-
lpp = PageGetItemId(page, lineoff);
778-
for (;;)
761+
while (block != InvalidBlockNumber)
779762
{
763+
heapgetpage((TableScanDesc) scan, block);
764+
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
765+
page = heapgettup_start_page(scan, dir, &linesleft, &lineoff);
766+
continue_page:
767+
780768
/*
781769
* Only continue scanning the page while we have lines left.
782770
*
783771
* Note that this protects us from accessing line pointers past
784772
* PageGetMaxOffsetNumber(); both for forward scans when we resume the
785773
* table scan, and for when we start scanning a new page.
786774
*/
787-
while (linesleft > 0)
775+
for (; linesleft > 0; linesleft--, lineoff += dir)
788776
{
789-
if (ItemIdIsNormal(lpp))
790-
{
791-
bool valid;
777+
bool visible;
778+
ItemId lpp = PageGetItemId(page, lineoff);
792779

793-
tuple->t_data = (HeapTupleHeader) PageGetItem(page, lpp);
794-
tuple->t_len = ItemIdGetLength(lpp);
795-
ItemPointerSet(&(tuple->t_self), block, lineoff);
780+
if (!ItemIdIsNormal(lpp))
781+
continue;
796782

797-
/*
798-
* if current tuple qualifies, return it.
799-
*/
800-
valid = HeapTupleSatisfiesVisibility(tuple,
801-
scan->rs_base.rs_snapshot,
802-
scan->rs_cbuf);
783+
tuple->t_data = (HeapTupleHeader) PageGetItem(page, lpp);
784+
tuple->t_len = ItemIdGetLength(lpp);
785+
ItemPointerSet(&(tuple->t_self), block, lineoff);
803786

804-
HeapCheckForSerializableConflictOut(valid, scan->rs_base.rs_rd,
805-
tuple, scan->rs_cbuf,
806-
scan->rs_base.rs_snapshot);
787+
visible = HeapTupleSatisfiesVisibility(tuple,
788+
scan->rs_base.rs_snapshot,
789+
scan->rs_cbuf);
807790

808-
if (valid && key != NULL)
809-
valid = HeapKeyTest(tuple, RelationGetDescr(scan->rs_base.rs_rd),
810-
nkeys, key);
791+
HeapCheckForSerializableConflictOut(visible, scan->rs_base.rs_rd,
792+
tuple, scan->rs_cbuf,
793+
scan->rs_base.rs_snapshot);
811794

812-
if (valid)
813-
{
814-
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
815-
scan->rs_coffset = lineoff;
816-
return;
817-
}
818-
}
795+
/* skip tuples not visible to this snapshot */
796+
if (!visible)
797+
continue;
819798

820-
/*
821-
* otherwise move to the next item on the page
822-
*/
823-
--linesleft;
824-
if (backward)
825-
{
826-
--lpp; /* move back in this page's ItemId array */
827-
--lineoff;
828-
}
829-
else
830-
{
831-
++lpp; /* move forward in this page's ItemId array */
832-
++lineoff;
833-
}
799+
/* skip any tuples that don't match the scan key */
800+
if (key != NULL &&
801+
!HeapKeyTest(tuple, RelationGetDescr(scan->rs_base.rs_rd),
802+
nkeys, key))
803+
continue;
804+
805+
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
806+
scan->rs_coffset = lineoff;
807+
return;
834808
}
835809

836810
/*
@@ -841,40 +815,16 @@ heapgettup(HeapScanDesc scan,
841815

842816
/* get the BlockNumber to scan next */
843817
block = heapgettup_advance_block(scan, block, dir);
818+
}
844819

845-
/*
846-
* return NULL if we've exhausted all the pages
847-
*/
848-
if (block == InvalidBlockNumber)
849-
{
850-
if (BufferIsValid(scan->rs_cbuf))
851-
ReleaseBuffer(scan->rs_cbuf);
852-
scan->rs_cbuf = InvalidBuffer;
853-
scan->rs_cblock = InvalidBlockNumber;
854-
tuple->t_data = NULL;
855-
scan->rs_inited = false;
856-
return;
857-
}
858-
859-
heapgetpage((TableScanDesc) scan, block);
860-
861-
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
820+
/* end of scan */
821+
if (BufferIsValid(scan->rs_cbuf))
822+
ReleaseBuffer(scan->rs_cbuf);
862823

863-
page = BufferGetPage(scan->rs_cbuf);
864-
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd,
865-
page);
866-
linesleft = PageGetMaxOffsetNumber(page);
867-
if (backward)
868-
{
869-
lineoff = linesleft;
870-
lpp = PageGetItemId(page, linesleft);
871-
}
872-
else
873-
{
874-
lineoff = FirstOffsetNumber;
875-
lpp = PageGetItemId(page, FirstOffsetNumber);
876-
}
877-
}
824+
scan->rs_cbuf = InvalidBuffer;
825+
scan->rs_cblock = InvalidBlockNumber;
826+
tuple->t_data = NULL;
827+
scan->rs_inited = false;
878828
}
879829

880830
/* ----------------
@@ -897,35 +847,16 @@ heapgettup_pagemode(HeapScanDesc scan,
897847
ScanKey key)
898848
{
899849
HeapTuple tuple = &(scan->rs_ctup);
900-
bool backward = ScanDirectionIsBackward(dir);
901850
BlockNumber block;
902851
Page page;
903852
int lineindex;
904-
OffsetNumber lineoff;
905853
int linesleft;
906-
ItemId lpp;
907854

908855
if (unlikely(!scan->rs_inited))
909856
{
910857
block = heapgettup_initial_block(scan, dir);
911-
912-
/*
913-
* Check if we have reached the end of the scan already. This could
914-
* happen if the table is empty or if the other workers in a parallel
915-
* scan have already finished the scan.
916-
*/
917-
if (block == InvalidBlockNumber)
918-
{
919-
Assert(!BufferIsValid(scan->rs_cbuf));
920-
tuple->t_data = NULL;
921-
return;
922-
}
923-
924-
heapgetpage((TableScanDesc) scan, block);
925-
page = BufferGetPage(scan->rs_cbuf);
926-
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
927-
linesleft = scan->rs_ntuples;
928-
lineindex = ScanDirectionIsForward(dir) ? 0 : linesleft - 1;
858+
/* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
859+
Assert(block != InvalidBlockNumber || !BufferIsValid(scan->rs_cbuf));
929860
scan->rs_inited = true;
930861
}
931862
else
@@ -940,16 +871,31 @@ heapgettup_pagemode(HeapScanDesc scan,
940871
linesleft = scan->rs_ntuples - lineindex;
941872
else
942873
linesleft = scan->rs_cindex;
874+
/* lineindex now references the next or previous visible tid */
875+
876+
goto continue_page;
943877
}
944878

945879
/*
946880
* advance the scan until we find a qualifying tuple or run out of stuff
947881
* to scan
948882
*/
949-
for (;;)
883+
while (block != InvalidBlockNumber)
950884
{
951-
while (linesleft > 0)
885+
heapgetpage((TableScanDesc) scan, block);
886+
page = BufferGetPage(scan->rs_cbuf);
887+
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
888+
linesleft = scan->rs_ntuples;
889+
lineindex = ScanDirectionIsForward(dir) ? 0 : linesleft - 1;
890+
891+
/* lineindex now references the next or previous visible tid */
892+
continue_page:
893+
894+
for (; linesleft > 0; linesleft--, lineindex += dir)
952895
{
896+
ItemId lpp;
897+
OffsetNumber lineoff;
898+
953899
lineoff = scan->rs_vistuples[lineindex];
954900
lpp = PageGetItemId(page, lineoff);
955901
Assert(ItemIdIsNormal(lpp));
@@ -958,64 +904,27 @@ heapgettup_pagemode(HeapScanDesc scan,
958904
tuple->t_len = ItemIdGetLength(lpp);
959905
ItemPointerSet(&(tuple->t_self), block, lineoff);
960906

961-
/*
962-
* if current tuple qualifies, return it.
963-
*/
964-
if (key != NULL)
965-
{
966-
bool valid;
967-
968-
valid = HeapKeyTest(tuple, RelationGetDescr(scan->rs_base.rs_rd),
969-
nkeys, key);
970-
if (valid)
971-
{
972-
scan->rs_cindex = lineindex;
973-
return;
974-
}
975-
}
976-
else
977-
{
978-
scan->rs_cindex = lineindex;
979-
return;
980-
}
907+
/* skip any tuples that don't match the scan key */
908+
if (key != NULL &&
909+
!HeapKeyTest(tuple, RelationGetDescr(scan->rs_base.rs_rd),
910+
nkeys, key))
911+
continue;
981912

982-
/*
983-
* otherwise move to the next item on the page
984-
*/
985-
--linesleft;
986-
if (backward)
987-
--lineindex;
988-
else
989-
++lineindex;
913+
scan->rs_cindex = lineindex;
914+
return;
990915
}
991916

992917
/* get the BlockNumber to scan next */
993918
block = heapgettup_advance_block(scan, block, dir);
994-
995-
/*
996-
* return NULL if we've exhausted all the pages
997-
*/
998-
if (block == InvalidBlockNumber)
999-
{
1000-
if (BufferIsValid(scan->rs_cbuf))
1001-
ReleaseBuffer(scan->rs_cbuf);
1002-
scan->rs_cbuf = InvalidBuffer;
1003-
scan->rs_cblock = InvalidBlockNumber;
1004-
tuple->t_data = NULL;
1005-
scan->rs_inited = false;
1006-
return;
1007-
}
1008-
1009-
heapgetpage((TableScanDesc) scan, block);
1010-
1011-
page = BufferGetPage(scan->rs_cbuf);
1012-
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
1013-
linesleft = scan->rs_ntuples;
1014-
if (backward)
1015-
lineindex = linesleft - 1;
1016-
else
1017-
lineindex = 0;
1018919
}
920+
921+
/* end of scan */
922+
if (BufferIsValid(scan->rs_cbuf))
923+
ReleaseBuffer(scan->rs_cbuf);
924+
scan->rs_cbuf = InvalidBuffer;
925+
scan->rs_cblock = InvalidBlockNumber;
926+
tuple->t_data = NULL;
927+
scan->rs_inited = false;
1019928
}
1020929

1021930

0 commit comments

Comments
 (0)