@@ -96,19 +96,49 @@ static void dataPlaceToPageLeafSplit(Buffer buf,
9696 XLogRecData * * prdata , Page lpage , Page rpage );
9797
9898/*
99- * Read all TIDs from leaf data page to single uncompressed array.
99+ * Read TIDs from leaf data page to single uncompressed array. The TIDs are
100+ * returned in ascending order.
101+ *
102+ * advancePast is a hint, indicating that the caller is only interested in
103+ * TIDs > advancePast. To return all items, use ItemPointerSetMin.
104+ *
105+ * Note: This function can still return items smaller than advancePast that
106+ * are in the same posting list as the items of interest, so the caller must
107+ * still check all the returned items. But passing it allows this function to
108+ * skip whole posting lists.
100109 */
101110ItemPointer
102- GinDataLeafPageGetItems (Page page , int * nitems )
111+ GinDataLeafPageGetItems (Page page , int * nitems , ItemPointerData advancePast )
103112{
104113 ItemPointer result ;
105114
106115 if (GinPageIsCompressed (page ))
107116 {
108- GinPostingList * ptr = GinDataLeafPageGetPostingList (page );
117+ GinPostingList * seg = GinDataLeafPageGetPostingList (page );
109118 Size len = GinDataLeafPageGetPostingListSize (page );
119+ Pointer endptr = ((Pointer ) seg ) + len ;
120+ GinPostingList * next ;
121+
122+ /* Skip to the segment containing advancePast+1 */
123+ if (ItemPointerIsValid (& advancePast ))
124+ {
125+ next = GinNextPostingListSegment (seg );
126+ while ((Pointer ) next < endptr &&
127+ ginCompareItemPointers (& next -> first , & advancePast ) <= 0 )
128+ {
129+ seg = next ;
130+ next = GinNextPostingListSegment (seg );
131+ }
132+ len = endptr - (Pointer ) seg ;
133+ }
110134
111- result = ginPostingListDecodeAllSegments (ptr , len , nitems );
135+ if (len > 0 )
136+ result = ginPostingListDecodeAllSegments (seg , len , nitems );
137+ else
138+ {
139+ result = NULL ;
140+ * nitems = 0 ;
141+ }
112142 }
113143 else
114144 {
0 commit comments