Skip to content

Commit

Permalink
Fixed CORE-2457 - UNICODE_CI internal gds software consistency check.
Browse files Browse the repository at this point in the history
  • Loading branch information
asfernandes committed Jan 24, 2012
1 parent ccc264f commit a62c4b1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 43 deletions.
73 changes: 30 additions & 43 deletions src/jrd/Optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ IndexScratch::IndexScratch(MemoryPool& p, thread_db* tdbb, index_desc* ix,
lowerCount = 0;
upperCount = 0;
nonFullMatchedSegments = 0;
fuzzy = false;

segments.grow(idx->idx_count);

Expand Down Expand Up @@ -315,6 +316,7 @@ IndexScratch::IndexScratch(MemoryPool& p, const IndexScratch& scratch) :
lowerCount = scratch.lowerCount;
upperCount = scratch.upperCount;
nonFullMatchedSegments = scratch.nonFullMatchedSegments;
fuzzy = scratch.fuzzy;
idx = scratch.idx;

// Allocate needed segments
Expand Down Expand Up @@ -849,6 +851,7 @@ void OptimizerRetrieval::getInversionCandidates(InversionCandidateList* inversio
scratch.lowerCount = 0;
scratch.upperCount = 0;
scratch.nonFullMatchedSegments = MAX_INDEX_SEGMENTS + 1;
scratch.fuzzy = false;

if (scratch.candidate)
{
Expand All @@ -864,10 +867,29 @@ void OptimizerRetrieval::getInversionCandidates(InversionCandidateList* inversio
if (segment->scope == scope)
scratch.scopeCandidate = true;

if (segment->scanType != segmentScanMissing && !(scratch.idx->idx_flags & idx_unique))
{
const USHORT iType = scratch.idx->idx_rpt[j].idx_itype;

if (iType >= idx_first_intl_string)
{
TextType* textType = INTL_texttype_lookup(tdbb, INTL_INDEX_TO_TEXT(iType));

if (textType->getFlags() & TEXTTYPE_SEPARATE_UNIQUE)
{
// ASF: Order is more precise than equivalence class.
// We can't use the next segments, and we'll need to use
// INTL_KEY_PARTIAL to construct the last segment's key.
scratch.fuzzy = true;;
}
}
}

// Check if this is the last usable segment
if (((segment->scanType == segmentScanEqual) ||
(segment->scanType == segmentScanEquivalent) ||
(segment->scanType == segmentScanMissing)))
if (!scratch.fuzzy &&
(segment->scanType == segmentScanEqual ||
segment->scanType == segmentScanEquivalent ||
segment->scanType == segmentScanMissing))
{
// This is a perfect usable segment thus update root selectivity
scratch.lowerCount++;
Expand Down Expand Up @@ -934,13 +956,16 @@ void OptimizerRetrieval::getInversionCandidates(InversionCandidateList* inversio
break;

case segmentScanStarting:
case segmentScanEqual:
case segmentScanEquivalent:
scratch.lowerCount++;
scratch.upperCount++;
selectivity = scratch.idx->idx_rpt[j].idx_selectivity;
factor = REDUCE_SELECTIVITY_FACTOR_STARTING;
break;

default:
fb_assert(segment->scanType == segmentScanNone);
break;
}

Expand Down Expand Up @@ -1157,46 +1182,8 @@ InversionNode* OptimizerRetrieval::makeIndexScanNode(IndexScratch* indexScratch)
retrieval->irb_generic |= irb_exclude_upper;
}

for (IndexScratchSegment** tail = indexScratch->segments.begin();
tail != indexScratch->segments.end() && ((*tail)->lowerValue || (*tail)->upperValue); ++tail)
{
ComparativeBoolNode* cmpNode = (*tail)->matches[0]->as<ComparativeBoolNode>();
fb_assert(cmpNode);

dsc dsc0;
cmpNode->arg1->getDesc(tdbb, csb, &dsc0);

// ASF: "dsc0.dsc_ttype() > ttype_last_internal" is to avoid recursion
// when looking for charsets/collations
if (!(indexScratch->idx->idx_flags & idx_unique) && DTYPE_IS_TEXT(dsc0.dsc_dtype) &&
dsc0.dsc_ttype() > ttype_last_internal)
{
TextType* tt = INTL_texttype_lookup(tdbb, dsc0.dsc_ttype());

if (tt->getFlags() & TEXTTYPE_SEPARATE_UNIQUE)
{
// ASF: Order is more precise than equivalence class.
// It's necessary to use the partial key.
retrieval->irb_generic |= irb_starting;

// For multi-segmented indices we can't use the remaining segments.
int diff = indexScratch->lowerCount - indexScratch->upperCount;

if (diff >= 0)
{
retrieval->irb_lower_count = tail - indexScratch->segments.begin() + 1;
retrieval->irb_upper_count = tail - indexScratch->segments.begin() + 1 - diff;
}
else
{
retrieval->irb_lower_count = tail - indexScratch->segments.begin() + 1 + diff;
retrieval->irb_upper_count = tail - indexScratch->segments.begin() + 1;
}

break;
}
}
}
if (indexScratch->fuzzy)
retrieval->irb_generic |= irb_starting; // Flag the need to use INTL_KEY_PARTIAL in btr.

// This index is never used for IS NULL, thus we can ignore NULLs
// already at index scan. But this rule doesn't apply to nod_equiv
Expand Down
1 change: 1 addition & 0 deletions src/jrd/Optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class IndexScratch
int lowerCount; //
int upperCount; //
int nonFullMatchedSegments; //
bool fuzzy; // Need to use INTL_KEY_PARTIAL in btr lookups
double cardinality; // Estimated cardinality when using the whole index

Firebird::Array<IndexScratchSegment*> segments;
Expand Down

0 comments on commit a62c4b1

Please sign in to comment.