+loop_top_fwd: |
<> |
+loop_top_bwd: |
+ /* load items[] in ascending order */ |
|
+ /* load items[] in descending order */ |
+ itemIndex = 0; |
|
+ itemIndex = MaxIndexTuplesPerPage; |
+ |
= |
+ |
+ /* new page, locate starting position by binary search */ |
|
+ /* new page, locate starting position by binary search */ |
+ offnum = _hash_binsearch(page, so->hashso_sk_hash); |
<> |
+ offnum = _hash_binsearch_last(page, so->hashso_sk_hash); |
+ |
= |
+ |
+ while (offnum <= maxoff) |
<> |
+ while (offnum >= FirstOffsetNumber) |
+ { |
= |
+ { |
+ Assert(offnum >= FirstOffsetNumber); |
<> |
+ Assert(offnum <= maxoff); |
+ itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum)); |
= |
+ itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum)); |
+ |
|
+ |
+ /* |
|
+ /* |
+ * skip the tuples that are moved by split operation |
|
+ * skip the tuples that are moved by split operation |
+ * for the scan that has started when split was in |
|
+ * for the scan that has started when split was in |
+ * progress. Also, skip the tuples that are marked |
|
+ * progress. Also, skip the tuples that are marked |
+ * as dead. |
|
+ * as dead. |
+ */ |
|
+ */ |
+ if ((so->hashso_buc_populated && !so->hashso_buc_split && |
|
+ if ((so->hashso_buc_populated && !so->hashso_buc_split && |
+ (itup->t_info & INDEX_MOVED_BY_SPLIT_MASK)) || |
|
+ (itup->t_info & INDEX_MOVED_BY_SPLIT_MASK)) || |
+ (scan->ignore_killed_tuples && |
|
+ (scan->ignore_killed_tuples && |
+ (ItemIdIsDead(PageGetItemId(page, offnum))))) |
|
+ (ItemIdIsDead(PageGetItemId(page, offnum))))) |
+ { |
|
+ { |
+ offnum = OffsetNumberNext(offnum); /* move forward */ |
<> |
+ offnum = OffsetNumberPrev(offnum); /* move back */ |
+ continue; |
= |
+ continue; |
+ } |
|
+ } |
+ |
|
+ |
+ if (so->hashso_sk_hash == _hash_get_indextuple_hashkey(itup) && |
|
+ if (so->hashso_sk_hash == _hash_get_indextuple_hashkey(itup) && |
+ _hash_checkqual(scan, itup)) |
|
+ _hash_checkqual(scan, itup)) |
+ { |
|
+ { |
|
-+ |
+ itemIndex--; |
+ /* tuple is qualified, so remember it */ |
= |
+ /* tuple is qualified, so remember it */ |
+ _hash_saveitem(so, itemIndex, offnum, itup); |
|
+ _hash_saveitem(so, itemIndex, offnum, itup); |
+ itemIndex++; |
+- |
|
+ } |
= |
+ } |
+ |
|
+ |
+ offnum = OffsetNumberNext(offnum); |
<> |
+ offnum = OffsetNumberPrev(offnum); |
+ } |
= |
+ } |
+ |
|
+ |
+ Assert(itemIndex <= MaxIndexTuplesPerPage); |
<> |
+ Assert(itemIndex >= 0); |
+ |
= |
+ |
+ if (itemIndex == 0) |
<> |
+ if (itemIndex == MaxIndexTuplesPerPage) |
+ { |
= |
+ { |
+ /* |
|
+ /* |
+ * Could not find any matching tuples in the current page, move |
|
+ * Could not find any matching tuples in the current page, move |
+ * to the next page. Before leaving the current page, also deal |
<> |
+ * to the prev page. Before leaving the current page, also deal |
+ * with any killed items. |
= |
+ * with any killed items. |
+ */ |
|
+ */ |
+ if (so->numKilled > 0) |
|
+ if (so->numKilled > 0) |
+ _hash_kill_items(scan); |
|
+ _hash_kill_items(scan); |
+ |
|
+ |
+ _hash_readnext(scan, &buf, &page, &opaque); |
<> |
+ _hash_readprev(scan, &buf, &page, &opaque); |
+ if (BufferIsValid(buf)) |
= |
+ if (BufferIsValid(buf)) |
+ { |
|
+ { |
+ so->currPos.buf = buf; |
|
+ so->currPos.buf = buf; |
+ so->currPos.currPage = BufferGetBlockNumber(buf); |
|
+ so->currPos.currPage = BufferGetBlockNumber(buf); |
+ maxoff = PageGetMaxOffsetNumber(page); |
|
+ maxoff = PageGetMaxOffsetNumber(page); |
+ offnum = _hash_binsearch(page, so->hashso_sk_hash); |
<> |
+ offnum = _hash_binsearch_last(page, so->hashso_sk_hash); |
+ goto loop_top_fwd; |
|
+ goto loop_top_bwd; |
+ } |
= |
+ } |
+ else |
|
+ else |
+ return false; |
|
+ return false; |
+ } |
|
+ } |
+ else |
|
+ else |
+ { |
|
+ { |
+ if (so->currPos.buf == so->hashso_bucket_buf || |
|
+ if (so->currPos.buf == so->hashso_bucket_buf || |
+ so->currPos.buf == so->hashso_split_bucket_buf) |
|
+ so->currPos.buf == so->hashso_split_bucket_buf) |
+ LockBuffer(so->currPos.buf, BUFFER_LOCK_UNLOCK); |
|
+ LockBuffer(so->currPos.buf, BUFFER_LOCK_UNLOCK); |
+ else |
|
+ else |
+ _hash_relbuf(rel, so->currPos.buf); |
|
+ _hash_relbuf(rel, so->currPos.buf); |
+ |
<> |
|
+ so->currPos.nextPage = (opaque)->hasho_nextblkno; |
|
+ so->currPos.prevPage = (opaque)->hasho_prevblkno; |
+ } |
= |
+ } |
+ |
|
+ |
+ so->currPos.firstItem = 0; |
<> |
+ so->currPos.firstItem = itemIndex; |
+ so->currPos.lastItem = itemIndex - 1; |
|
+ so->currPos.lastItem = MaxIndexTuplesPerPage - 1; |
+ so->currPos.itemIndex = 0; |
|
+ so->currPos.itemIndex = MaxIndexTuplesPerPage - 1; |
+ } |
= |
+ } |
|
|
|