mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:43:02 +01:00
Rework fix for #8290: Unique scan is incorrectly reported in the explained plan for unique index and IS NULL predicate
This commit is contained in:
parent
5ed57cb43b
commit
e7e9e01fa9
@ -6769,7 +6769,7 @@ static bool scan(thread_db* tdbb, UCHAR* pointer, RecordBitmap** bitmap, RecordB
|
||||
const bool partUpper = (retrieval->irb_upper_count < idx->idx_count);
|
||||
|
||||
// Reset flags this routine does not check in the loop below
|
||||
flag &= ~(irb_equality | irb_ignore_null_value_key | irb_root_list_scan);
|
||||
flag &= ~(irb_equality | irb_unique | irb_ignore_null_value_key | irb_root_list_scan);
|
||||
flag &= ~(irb_exclude_lower | irb_exclude_upper);
|
||||
|
||||
IndexNode node;
|
||||
|
@ -237,6 +237,7 @@ const int irb_exclude_lower = 32; // exclude lower bound keys while scanning i
|
||||
const int irb_exclude_upper = 64; // exclude upper bound keys while scanning index
|
||||
const int irb_multi_starting = 128; // Use INTL_KEY_MULTI_STARTING
|
||||
const int irb_root_list_scan = 256; // Locate list items from the root
|
||||
const int irb_unique = 512; // Unique match (currently used only for plan output)
|
||||
|
||||
// Force include flags - always include appropriate key while scanning index
|
||||
const int irb_force_lower = irb_exclude_lower;
|
||||
|
@ -1245,6 +1245,9 @@ InversionNode* Retrieval::makeIndexScanNode(IndexScratch* indexScratch) const
|
||||
// Check to see if this is really an equality retrieval
|
||||
if (retrieval->irb_lower_count == retrieval->irb_upper_count)
|
||||
{
|
||||
const bool fullMatch = (retrieval->irb_lower_count == idx->idx_count);
|
||||
bool uniqueMatch = false;
|
||||
|
||||
retrieval->irb_generic |= irb_equality;
|
||||
|
||||
for (unsigned i = 0; i < retrieval->irb_lower_count; i++)
|
||||
@ -1254,7 +1257,22 @@ InversionNode* Retrieval::makeIndexScanNode(IndexScratch* indexScratch) const
|
||||
retrieval->irb_generic &= ~irb_equality;
|
||||
break;
|
||||
}
|
||||
|
||||
if (segments[i].scanType == segmentScanMissing ||
|
||||
segments[i].scanType == segmentScanEquivalent)
|
||||
{
|
||||
if (fullMatch && (idx->idx_flags & idx_primary))
|
||||
uniqueMatch = true;
|
||||
}
|
||||
else if (segments[i].scanType == segmentScanEqual)
|
||||
{
|
||||
if (fullMatch && (idx->idx_flags & idx_unique))
|
||||
uniqueMatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((retrieval->irb_generic & irb_equality) && uniqueMatch)
|
||||
retrieval->irb_generic |= irb_unique;
|
||||
}
|
||||
|
||||
// If we are matching less than the full index, this is a partial match
|
||||
|
@ -203,26 +203,18 @@ void RecordSource::printInversion(thread_db* tdbb, const InversionNode* inversio
|
||||
}
|
||||
|
||||
const index_desc& idx = retrieval->irb_desc;
|
||||
const bool primaryIdx = (idx.idx_flags & idx_primary);
|
||||
const bool uniqueIdx = (idx.idx_flags & idx_unique);
|
||||
const USHORT segCount = idx.idx_count;
|
||||
|
||||
const USHORT minSegs = MIN(retrieval->irb_lower_count, retrieval->irb_upper_count);
|
||||
const USHORT maxSegs = MAX(retrieval->irb_lower_count, retrieval->irb_upper_count);
|
||||
|
||||
const bool equality = (retrieval->irb_generic & irb_equality);
|
||||
const bool unique = (retrieval->irb_generic & irb_unique);
|
||||
const bool partial = (retrieval->irb_generic & irb_partial);
|
||||
|
||||
const bool fullscan = (maxSegs == 0);
|
||||
const bool list = (retrieval->irb_list != nullptr);
|
||||
|
||||
bool unique = false;
|
||||
if (!list && equality && minSegs == segCount)
|
||||
{
|
||||
unique = (retrieval->irb_generic & irb_ignore_null_value_key) ?
|
||||
uniqueIdx : primaryIdx;
|
||||
}
|
||||
|
||||
string bounds;
|
||||
if (!unique && !fullscan)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user