diff --git a/src/jrd/opt.cpp b/src/jrd/opt.cpp index 42d04dedd7..549534e0b2 100644 --- a/src/jrd/opt.cpp +++ b/src/jrd/opt.cpp @@ -2379,8 +2379,7 @@ static RecordSource* gen_retrieval(thread_db* tdbb, if (sort_ptr) *sort_ptr = NULL; - if (inversion && !condition) - nav_rsb->setInversion(inversion); + nav_rsb->setInversion(inversion, condition); rsb = nav_rsb; } diff --git a/src/jrd/recsrc/IndexTableScan.cpp b/src/jrd/recsrc/IndexTableScan.cpp index 436b551e31..85ba7c3103 100644 --- a/src/jrd/recsrc/IndexTableScan.cpp +++ b/src/jrd/recsrc/IndexTableScan.cpp @@ -42,8 +42,8 @@ using namespace Jrd; IndexTableScan::IndexTableScan(CompilerScratch* csb, const string& name, StreamType stream, InversionNode* index, USHORT length) - : RecordStream(csb, stream), m_name(csb->csb_pool, name), m_index(index), m_inversion(NULL), - m_length(length), m_offset(0) + : RecordStream(csb, stream), m_name(csb->csb_pool, name), m_index(index), + m_inversion(NULL), m_condition(NULL), m_length(length), m_offset(0) { fb_assert(m_index); @@ -191,7 +191,7 @@ bool IndexTableScan::getRecord(thread_db* tdbb) const // is not in the bitmap for the inversion, or // 2) the record has already been visited - if ((m_inversion && + if ((!(impure->irsb_flags & irsb_mustread) && (!impure->irsb_nav_bitmap || !RecordBitmap::test(*impure->irsb_nav_bitmap, number.getValue()))) || RecordBitmap::test(impure->irsb_nav_records_visited, number.getValue())) @@ -593,6 +593,7 @@ bool IndexTableScan::setupBitmaps(thread_db* tdbb, Impure* impure) const // than one leaf node reference to the same record number; the // bitmap allows us to filter out the multiple references. RecordBitmap::reset(impure->irsb_nav_records_visited); + impure->irsb_flags |= irsb_mustread; // the first time we open the stream, compute a bitmap // for the inversion tree -- this may cause problems for @@ -600,10 +601,14 @@ bool IndexTableScan::setupBitmaps(thread_db* tdbb, Impure* impure) const // view of the database when the stream is opened if (m_inversion) { - // There is no need to reset or release the bitmap, it is - // done in EVL_bitmap() - impure->irsb_nav_bitmap = EVL_bitmap(tdbb, m_inversion, NULL); - return (*impure->irsb_nav_bitmap != NULL); + if (!m_condition || !m_condition->execute(tdbb, tdbb->getRequest())) + { + impure->irsb_flags &= ~irsb_mustread; + // There is no need to reset or release the bitmap, it is + // done in EVL_bitmap() + impure->irsb_nav_bitmap = EVL_bitmap(tdbb, m_inversion, NULL); + return (*impure->irsb_nav_bitmap != NULL); + } } return true; diff --git a/src/jrd/recsrc/RecordSource.h b/src/jrd/recsrc/RecordSource.h index 53bce19ddf..9df04783e7 100644 --- a/src/jrd/recsrc/RecordSource.h +++ b/src/jrd/recsrc/RecordSource.h @@ -205,10 +205,11 @@ namespace Jrd void print(thread_db* tdbb, Firebird::string& plan, bool detailed, unsigned level) const; - void setInversion(InversionNode* inversion) + void setInversion(InversionNode* inversion, BoolExprNode* condition) { - fb_assert(!m_inversion); + fb_assert(!m_inversion && !m_condition); m_inversion = inversion; + m_condition = condition; } private: @@ -224,6 +225,7 @@ namespace Jrd const Firebird::string m_name; NestConst const m_index; NestConst m_inversion; + NestConst m_condition; const size_t m_length; size_t m_offset; };