/* * Return the offset of the next matching index entry. We begin the * search at offset "n" and search for matches in the direction * "dir". If no more matching entries are found on the page, * InvalidOffsetNumber is returned. */ static OffsetNumber findnext(IndexScanDesc s, OffsetNumber n, ScanDirection dir) { OffsetNumber maxoff; IndexTuple it; RTreePageOpaque po; RTreeScanOpaque so; Page p; so = (RTreeScanOpaque) s->opaque; p = BufferGetPage(so->curbuf); maxoff = PageGetMaxOffsetNumber(p); po = (RTreePageOpaque) PageGetSpecialPointer(p); /* * If we modified the index during the scan, we may have a pointer to a * ghost tuple, before the scan. If this is the case, back up one. */ if (so->s_flags & RTS_CURBEFORE) { so->s_flags &= ~RTS_CURBEFORE; n = OffsetNumberPrev(n); } while (n >= FirstOffsetNumber && n <= maxoff) { it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n)); if (po->flags & F_LEAF) { if (index_keytest(it, RelationGetDescr(s->indexRelation), s->numberOfKeys, s->keyData)) break; } else { if (index_keytest(it, RelationGetDescr(s->indexRelation), so->s_internalNKey, so->s_internalKey)) break; } if (ScanDirectionIsBackward(dir)) n = OffsetNumberPrev(n); else n = OffsetNumberNext(n); } if (n >= FirstOffsetNumber && n <= maxoff) return n; /* found a match on this page */ else return InvalidOffsetNumber; /* no match, go to next page */ }
/* * _hash_checkqual -- does the index tuple satisfy the scan conditions? */ bool _hash_checkqual(IndexScanDesc scan, IndexTuple itup) { return index_keytest(itup, RelationGetDescr(scan->indexRelation), scan->numberOfKeys, scan->keyData); }