Skip to content

Commit e7e9e01

Browse files
committed
Rework fix for #8290: Unique scan is incorrectly reported in the explained plan for unique index and IS NULL predicate
1 parent 5ed57cb commit e7e9e01

File tree

4 files changed

+21
-10
lines changed

4 files changed

+21
-10
lines changed

src/jrd/btr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6769,7 +6769,7 @@ static bool scan(thread_db* tdbb, UCHAR* pointer, RecordBitmap** bitmap, RecordB
67696769
const bool partUpper = (retrieval->irb_upper_count < idx->idx_count);
67706770

67716771
// Reset flags this routine does not check in the loop below
6772-
flag &= ~(irb_equality | irb_ignore_null_value_key | irb_root_list_scan);
6772+
flag &= ~(irb_equality | irb_unique | irb_ignore_null_value_key | irb_root_list_scan);
67736773
flag &= ~(irb_exclude_lower | irb_exclude_upper);
67746774

67756775
IndexNode node;

src/jrd/btr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ const int irb_exclude_lower = 32; // exclude lower bound keys while scanning i
237237
const int irb_exclude_upper = 64; // exclude upper bound keys while scanning index
238238
const int irb_multi_starting = 128; // Use INTL_KEY_MULTI_STARTING
239239
const int irb_root_list_scan = 256; // Locate list items from the root
240+
const int irb_unique = 512; // Unique match (currently used only for plan output)
240241

241242
// Force include flags - always include appropriate key while scanning index
242243
const int irb_force_lower = irb_exclude_lower;

src/jrd/optimizer/Retrieval.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,9 @@ InversionNode* Retrieval::makeIndexScanNode(IndexScratch* indexScratch) const
12451245
// Check to see if this is really an equality retrieval
12461246
if (retrieval->irb_lower_count == retrieval->irb_upper_count)
12471247
{
1248+
const bool fullMatch = (retrieval->irb_lower_count == idx->idx_count);
1249+
bool uniqueMatch = false;
1250+
12481251
retrieval->irb_generic |= irb_equality;
12491252

12501253
for (unsigned i = 0; i < retrieval->irb_lower_count; i++)
@@ -1254,7 +1257,22 @@ InversionNode* Retrieval::makeIndexScanNode(IndexScratch* indexScratch) const
12541257
retrieval->irb_generic &= ~irb_equality;
12551258
break;
12561259
}
1260+
1261+
if (segments[i].scanType == segmentScanMissing ||
1262+
segments[i].scanType == segmentScanEquivalent)
1263+
{
1264+
if (fullMatch && (idx->idx_flags & idx_primary))
1265+
uniqueMatch = true;
1266+
}
1267+
else if (segments[i].scanType == segmentScanEqual)
1268+
{
1269+
if (fullMatch && (idx->idx_flags & idx_unique))
1270+
uniqueMatch = true;
1271+
}
12571272
}
1273+
1274+
if ((retrieval->irb_generic & irb_equality) && uniqueMatch)
1275+
retrieval->irb_generic |= irb_unique;
12581276
}
12591277

12601278
// If we are matching less than the full index, this is a partial match

src/jrd/recsrc/RecordSource.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -203,26 +203,18 @@ void RecordSource::printInversion(thread_db* tdbb, const InversionNode* inversio
203203
}
204204

205205
const index_desc& idx = retrieval->irb_desc;
206-
const bool primaryIdx = (idx.idx_flags & idx_primary);
207-
const bool uniqueIdx = (idx.idx_flags & idx_unique);
208206
const USHORT segCount = idx.idx_count;
209207

210208
const USHORT minSegs = MIN(retrieval->irb_lower_count, retrieval->irb_upper_count);
211209
const USHORT maxSegs = MAX(retrieval->irb_lower_count, retrieval->irb_upper_count);
212210

213211
const bool equality = (retrieval->irb_generic & irb_equality);
212+
const bool unique = (retrieval->irb_generic & irb_unique);
214213
const bool partial = (retrieval->irb_generic & irb_partial);
215214

216215
const bool fullscan = (maxSegs == 0);
217216
const bool list = (retrieval->irb_list != nullptr);
218217

219-
bool unique = false;
220-
if (!list && equality && minSegs == segCount)
221-
{
222-
unique = (retrieval->irb_generic & irb_ignore_null_value_key) ?
223-
uniqueIdx : primaryIdx;
224-
}
225-
226218
string bounds;
227219
if (!unique && !fullscan)
228220
{

0 commit comments

Comments
 (0)