@ -1429,6 +1429,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
/* remember which buffer we have pinned, if any */
/* remember which buffer we have pinned, if any */
Assert ( ! BTScanPosIsValid ( so - > currPos ) ) ;
Assert ( ! BTScanPosIsValid ( so - > currPos ) ) ;
so - > currPos . buf = buf ;
so - > currPos . buf = buf ;
so - > firstPage = true ;
/*
/*
* Now load data from the first page of the scan .
* Now load data from the first page of the scan .
@ -1539,6 +1540,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
int itemIndex ;
int itemIndex ;
bool continuescan ;
bool continuescan ;
int indnatts ;
int indnatts ;
bool requiredMatchedByPrecheck ;
/*
/*
* We must have the buffer pinned and locked , but the usual macro can ' t be
* We must have the buffer pinned and locked , but the usual macro can ' t be
@ -1592,6 +1594,46 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
*/
*/
Assert ( BTScanPosIsPinned ( so - > currPos ) ) ;
Assert ( BTScanPosIsPinned ( so - > currPos ) ) ;
/*
* Prechecking the page with scan keys required for direction scan . We
* check these keys with the last item on the page ( according to our scan
* direction ) . If these keys are matched , we can skip checking them with
* every item on the page . Scan keys for our scan direction would
* necessarily match the previous items . Scan keys required for opposite
* direction scan are already matched by the _bt_first ( ) call .
*
* With the forward scan , we do this check for the last item on the page
* instead of the high key . It ' s relatively likely that the most
* significant column in the high key will be different from the
* corresponding value from the last item on the page . So checking with
* the last item on the page would give a more precise answer .
*
* We skip this for the first page in the scan to evade the possible
* slowdown of the point queries .
*/
if ( ! so - > firstPage & & minoff < maxoff )
{
ItemId iid ;
IndexTuple itup ;
iid = PageGetItemId ( page , ScanDirectionIsForward ( dir ) ? maxoff : minoff ) ;
itup = ( IndexTuple ) PageGetItem ( page , iid ) ;
/*
* Do the precheck . Note that we pass the pointer to
* ' requiredMatchedByPrecheck ' to ' continuescan ' argument . That will
* set flag to true if all required keys are satisfied and false
* otherwise .
*/
( void ) _bt_checkkeys ( scan , itup , indnatts , dir ,
& requiredMatchedByPrecheck , false ) ;
}
else
{
so - > firstPage = false ;
requiredMatchedByPrecheck = false ;
}
if ( ScanDirectionIsForward ( dir ) )
if ( ScanDirectionIsForward ( dir ) )
{
{
/* load items[] in ascending order */
/* load items[] in ascending order */
@ -1603,6 +1645,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
{
{
ItemId iid = PageGetItemId ( page , offnum ) ;
ItemId iid = PageGetItemId ( page , offnum ) ;
IndexTuple itup ;
IndexTuple itup ;
bool passes_quals ;
/*
/*
* If the scan specifies not to return killed tuples , then we
* If the scan specifies not to return killed tuples , then we
@ -1616,7 +1659,18 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
itup = ( IndexTuple ) PageGetItem ( page , iid ) ;
itup = ( IndexTuple ) PageGetItem ( page , iid ) ;
if ( _bt_checkkeys ( scan , itup , indnatts , dir , & continuescan ) )
passes_quals = _bt_checkkeys ( scan , itup , indnatts , dir ,
& continuescan , requiredMatchedByPrecheck ) ;
/*
* If the result of prechecking required keys was true , then in
* assert - enabled builds we also recheck that _bt_checkkeys ( )
* result is is the same .
*/
Assert ( ! requiredMatchedByPrecheck | |
passes_quals = = _bt_checkkeys ( scan , itup , indnatts , dir ,
& continuescan , false ) ) ;
if ( passes_quals )
{
{
/* tuple passes all scan key conditions */
/* tuple passes all scan key conditions */
if ( ! BTreeTupleIsPosting ( itup ) )
if ( ! BTreeTupleIsPosting ( itup ) )
@ -1673,7 +1727,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
int truncatt ;
int truncatt ;
truncatt = BTreeTupleGetNAtts ( itup , scan - > indexRelation ) ;
truncatt = BTreeTupleGetNAtts ( itup , scan - > indexRelation ) ;
_bt_checkkeys ( scan , itup , truncatt , dir , & continuescan ) ;
_bt_checkkeys ( scan , itup , truncatt , dir , & continuescan , false ) ;
}
}
if ( ! continuescan )
if ( ! continuescan )
@ -1725,7 +1779,16 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
itup = ( IndexTuple ) PageGetItem ( page , iid ) ;
itup = ( IndexTuple ) PageGetItem ( page , iid ) ;
passes_quals = _bt_checkkeys ( scan , itup , indnatts , dir ,
passes_quals = _bt_checkkeys ( scan , itup , indnatts , dir ,
& continuescan ) ;
& continuescan , requiredMatchedByPrecheck ) ;
/*
* If the result of prechecking required keys was true , then in
* assert - enabled builds we also recheck that _bt_checkkeys ( )
* result is is the same .
*/
Assert ( ! requiredMatchedByPrecheck | |
passes_quals = = _bt_checkkeys ( scan , itup , indnatts , dir ,
& continuescan , false ) ) ;
if ( passes_quals & & tuple_alive )
if ( passes_quals & & tuple_alive )
{
{
/* tuple passes all scan key conditions */
/* tuple passes all scan key conditions */
@ -2443,6 +2506,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
/* remember which buffer we have pinned */
/* remember which buffer we have pinned */
so - > currPos . buf = buf ;
so - > currPos . buf = buf ;
so - > firstPage = true ;
_bt_initialize_more_data ( so , dir ) ;
_bt_initialize_more_data ( so , dir ) ;