8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 16:43:03 +01:00

Allow computable but non-invariant lists to be used for index lookup

This commit is contained in:
Dmitry Yemanov 2023-09-07 20:55:48 +03:00
parent 3408f30109
commit 5df6668c7b
3 changed files with 38 additions and 26 deletions

View File

@ -1368,10 +1368,9 @@ void InListBoolNode::pass2Boolean(thread_db* tdbb, CompilerScratch* csb, std::fu
}
if (nodFlags & FLAG_INVARIANT)
{
impureOffset = csb->allocImpure<impure_value>();
lookup = FB_NEW_POOL(csb->csb_pool) LookupValueList(csb->csb_pool, list, impureOffset);
}
lookup = FB_NEW_POOL(csb->csb_pool) LookupValueList(csb->csb_pool, list, impureOffset);
}
bool InListBoolNode::execute(thread_db* tdbb, Request* request) const

View File

@ -206,17 +206,10 @@ LookupValueList::LookupValueList(MemoryPool& pool, ValueListNode* values, ULONG
const SortedValueList* LookupValueList::init(thread_db* tdbb, Request* request) const
{
const auto impure = request->getImpure<impure_value>(m_impureOffset);
auto sortedList = impure->vlu_misc.vlu_sortedList;
if (!(impure->vlu_flags & VLU_computed))
auto createList = [&]()
{
delete impure->vlu_misc.vlu_sortedList;
impure->vlu_misc.vlu_sortedList = nullptr;
sortedList = impure->vlu_misc.vlu_sortedList =
FB_NEW_POOL(*tdbb->getDefaultPool())
SortedValueList(*tdbb->getDefaultPool(), m_values.getCount());
const auto sortedList = FB_NEW_POOL(*tdbb->getDefaultPool())
SortedValueList(*tdbb->getDefaultPool(), m_values.getCount());
sortedList->setSortMode(FB_ARRAY_SORT_MANUAL);
@ -228,10 +221,32 @@ const SortedValueList* LookupValueList::init(thread_db* tdbb, Request* request)
sortedList->sort();
impure->vlu_flags |= VLU_computed;
return sortedList;
};
// Non-zero impure offset means that the list expression is invariant,
// so the sorted list can be cached inside the impure area
if (m_impureOffset)
{
const auto impure = request->getImpure<impure_value>(m_impureOffset);
auto sortedList = impure->vlu_misc.vlu_sortedList;
if (!(impure->vlu_flags & VLU_computed))
{
delete impure->vlu_misc.vlu_sortedList;
impure->vlu_misc.vlu_sortedList = nullptr;
sortedList = impure->vlu_misc.vlu_sortedList = createList();
impure->vlu_flags |= VLU_computed;
}
return sortedList;
}
return sortedList;
// Otherwise, create a temporary list for early evaluation during index lookup
return createList();
}
TriState LookupValueList::find(thread_db* tdbb, Request* request, const ValueExprNode* value, const dsc* desc) const

View File

@ -1885,19 +1885,17 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
if (!((segment->scanType == segmentScanEqual) ||
(segment->scanType == segmentScanEquivalent)))
{
if (auto lookup = listNode->lookup)
fb_assert(listNode->lookup);
for (auto& item : *listNode->lookup)
{
for (auto& item : *lookup)
{
cast = nullptr; // create new cast node for every value
item = injectCast(csb, item, cast, matchDesc);
}
segment->lowerValue = segment->upperValue = nullptr;
segment->valueList = lookup;
segment->scanType = segmentScanList;
segment->excludeLower = false;
segment->excludeUpper = false;
cast = nullptr; // create new cast node for every value
item = injectCast(csb, item, cast, matchDesc);
}
segment->lowerValue = segment->upperValue = nullptr;
segment->valueList = listNode->lookup;
segment->scanType = segmentScanList;
segment->excludeLower = false;
segment->excludeUpper = false;
}
}
else if (missingNode)