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

Fixed memory leak in expression index

This commit is contained in:
AlexPeshkoff 2025-01-13 20:13:43 +03:00
parent 2bbfd526b5
commit fda52dd662
8 changed files with 41 additions and 32 deletions

View File

@ -10830,7 +10830,7 @@ MetaId StoreIndexNode::create(thread_db* tdbb, Cached::Relation* rel, jrd_tra* t
}
END_FOR
idx.idx_condition = nullptr;
idx.idx_condition_node = nullptr;
idx.idx_condition_statement = nullptr;
if (!IDX.RDB$CONDITION_BLR.NULL)
@ -10849,7 +10849,7 @@ MetaId StoreIndexNode::create(thread_db* tdbb, Cached::Relation* rel, jrd_tra* t
transaction);
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
idx.idx_condition, csb, false);
idx.idx_condition_node, csb, false);
idx.idx_flags |= idx_condition;
}
@ -11114,7 +11114,7 @@ MetaId StoreIndexNode::createExpression(thread_db* tdbb, Cached::Relation* rel,
transaction);
idx.idx_expression_statement = Statement::makeValueExpression(tdbb,
idx.idx_expression, idx.idx_expression_desc, csb, false);
idx.idx_expression_node, idx.idx_expression_desc, csb, false);
// fake a description of the index
@ -11147,7 +11147,7 @@ MetaId StoreIndexNode::createExpression(thread_db* tdbb, Cached::Relation* rel,
transaction);
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
idx.idx_condition, csb, false);
idx.idx_condition_node, csb, false);
idx.idx_flags |= idx_condition;
}

View File

@ -551,6 +551,18 @@ IndexVersion::IndexVersion(MemoryPool& p, Cached::Index* idp)
: perm(idp)
{ }
void IndexVersion::destroy(thread_db* tdbb, IndexVersion* idv)
{
if (idv->idv_expression_statement)
idv->idv_expression_statement->release(tdbb);
if (idv->idv_condition_statement)
idv->idv_condition_statement->release(tdbb);
delete idv;
}
void jrd_rel::releaseTriggers(thread_db* tdbb, bool destroy)
{
for (int n = 1; n < TRIGGER_MAX; ++n)

View File

@ -512,10 +512,7 @@ public:
return FB_NEW_POOL(p) IndexVersion(p, idp);
}
static void destroy(thread_db* tdbb, IndexVersion* idv)
{
delete idv;
}
static void destroy(thread_db* tdbb, IndexVersion* idv);
static Lock* makeLock(thread_db* tdbb, MemoryPool& p)
{

View File

@ -739,9 +739,9 @@ bool BTR_description(thread_db* tdbb, Cached::Relation* relation, index_root_pag
idx->idx_foreign_deps = nullptr;
idx->idx_primary_relation = 0;
idx->idx_primary_index = 0;
idx->idx_expression = nullptr;
idx->idx_expression_node = nullptr;
idx->idx_expression_statement = nullptr;
idx->idx_condition = nullptr;
idx->idx_condition_node = nullptr;
idx->idx_condition_statement = nullptr;
idx->idx_fraction = 1.0;
@ -761,13 +761,13 @@ bool BTR_description(thread_db* tdbb, Cached::Relation* relation, index_root_pag
if (idx->idx_flags & idx_expression)
{
MET_lookup_index_expression(tdbb, relation, idx);
fb_assert(idx->idx_expression);
fb_assert(idx->idx_expression_node);
}
if (idx->idx_flags & idx_condition)
{
MET_lookup_index_condition(tdbb, relation, idx);
fb_assert(idx->idx_condition);
fb_assert(idx->idx_condition_node);
}
return true;
@ -779,7 +779,7 @@ bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record
if (!(idx->idx_flags & idx_condition))
return true;
fb_assert(idx->idx_condition);
fb_assert(idx->idx_condition_node);
Request* const orgRequest = tdbb->getRequest();
Request* const conditionRequest = idx->idx_condition_statement->findRequest(tdbb);
@ -812,7 +812,7 @@ bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record
else
conditionRequest->validateTimeStamp();
result = idx->idx_condition->execute(tdbb, conditionRequest);
result = idx->idx_condition_node->execute(tdbb, conditionRequest);
}
catch (const Exception& ex)
{
@ -834,7 +834,7 @@ bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record
DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& notNull)
{
SET_TDBB(tdbb);
fb_assert(idx->idx_expression);
fb_assert(idx->idx_expression_node);
// check for recursive expression evaluation
Request* const org_request = tdbb->getRequest();
@ -871,7 +871,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool&
else
expr_request->validateTimeStamp();
if (!(result = EVL_expr(tdbb, expr_request, idx->idx_expression)))
if (!(result = EVL_expr(tdbb, expr_request, idx->idx_expression_node)))
result = &idx->idx_expression_desc;
notNull = !(expr_request->req_flags & req_null);
@ -1730,7 +1730,7 @@ USHORT BTR_key_length(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
default:
if (idx->idx_flags & idx_expression)
{
fb_assert(idx->idx_expression);
fb_assert(idx->idx_expression_node);
length = idx->idx_expression_desc.dsc_length;
if (idx->idx_expression_desc.dsc_dtype == dtype_varying)
{

View File

@ -89,10 +89,10 @@ struct index_desc
MetaId idx_primary_relation; // id for primary key partner relation
USHORT idx_count; // number of keys
ForeignDeps* idx_foreign_deps; // foreign key partners
ValueExprNode* idx_expression; // node tree for indexed expression
ValueExprNode* idx_expression_node; // node tree for indexed expression
dsc idx_expression_desc; // descriptor for expression result
Statement* idx_expression_statement; // stored statement for expression evaluation
BoolExprNode* idx_condition; // node tree for index condition
BoolExprNode* idx_condition_node; // node tree for index condition
Statement* idx_condition_statement; // stored statement for index condition
float idx_fraction; // fraction of keys included in the index
// This structure should exactly match IRTD structure for current ODS

View File

@ -389,7 +389,7 @@ public:
m_idx = *creation->index; // copy
if (m_ownAttach)
{
m_idx.idx_expression = NULL;
m_idx.idx_expression_node = NULL;
m_idx.idx_expression_statement = NULL;
m_idx.idx_foreign_deps = NULL;
}
@ -546,14 +546,14 @@ bool IndexCreateTask::handler(WorkItem& _item)
partner_index_id = idx->idx_primary_index;
}
if ((idx->idx_flags & idx_expression) && (idx->idx_expression == NULL))
if ((idx->idx_flags & idx_expression) && (idx->idx_expression_node == NULL))
{
fb_assert(!m_exprBlob.isEmpty());
CompilerScratch* csb = NULL;
Jrd::ContextPoolHolder context(tdbb, dbb->createPool(ALLOC_ARGS0));
idx->idx_expression = static_cast<ValueExprNode*> (MET_parse_blob(tdbb, getPermanent(relation), &m_exprBlob,
idx->idx_expression_node = static_cast<ValueExprNode*> (MET_parse_blob(tdbb, getPermanent(relation), &m_exprBlob,
&csb, &idx->idx_expression_statement, false, false));
delete csb;

View File

@ -2276,7 +2276,7 @@ void MET_lookup_index_condition(thread_db* tdbb, Cached::Relation* relation, ind
IndexVersion* idv = relation->lookup_index(tdbb, idx->idx_id, CacheFlag::AUTOCREATE);
if (idv)
{
idx->idx_condition = idv->idv_condition;
idx->idx_condition_node = idv->idv_condition;
idx->idx_condition_statement = idv->idv_condition_statement;
}
}
@ -2299,7 +2299,7 @@ void MET_lookup_index_expression(thread_db* tdbb, Cached::Relation* relation, in
IndexVersion* idv = relation->lookup_index(tdbb, idx->idx_id, CacheFlag::AUTOCREATE);
if (idv)
{
idx->idx_expression = idv->idv_expression;
idx->idx_expression_node = idv->idv_expression;
idx->idx_expression_statement = idv->idv_expression_statement;
memcpy(&idx->idx_expression_desc, &idv->idv_expression_desc, sizeof(struct dsc));
}
@ -5294,7 +5294,7 @@ bool IndexVersion::scan(thread_db* tdbb, ObjectBase::Flag flags)
auto* relation = (expression.hasData() || condition.hasData()) ?
MetadataCache::lookupRelation(tdbb, relId, CacheFlag::AUTOCREATE) : nullptr;
perm->createLock(tdbb, relId, getId());
// ????? perm->createLock( caching lock
// ?????????????? perm->createLock( caching lock
if (expression.hasData())
{

View File

@ -701,9 +701,9 @@ bool Retrieval::betterInversion(const InversionCandidate* inv1,
bool Retrieval::checkIndexCondition(index_desc& idx, MatchedBooleanList& matches) const
{
fb_assert(idx.idx_condition);
fb_assert(idx.idx_condition_node);
if (!idx.idx_condition->containsStream(0, true))
if (!idx.idx_condition_node->containsStream(0, true))
return false;
fb_assert(matches.isEmpty());
@ -711,7 +711,7 @@ bool Retrieval::checkIndexCondition(index_desc& idx, MatchedBooleanList& matches
auto iter = optimizer->getConjuncts(outerFlag, innerFlag);
BoolExprNodeStack idxConjuncts;
const auto conjunctCount = optimizer->decomposeBoolean(idx.idx_condition, idxConjuncts);
const auto conjunctCount = optimizer->decomposeBoolean(idx.idx_condition_node, idxConjuncts);
fb_assert(conjunctCount);
idx.idx_fraction = MAXIMUM_SELECTIVITY;
@ -785,11 +785,11 @@ bool Retrieval::checkIndexCondition(index_desc& idx, MatchedBooleanList& matches
bool Retrieval::checkIndexExpression(const index_desc* idx, ValueExprNode* node) const
{
fb_assert(idx && idx->idx_expression);
fb_assert(idx && idx->idx_expression_node);
// The desired expression can be hidden inside a derived expression node,
// so try to recover it (see CORE-4118).
while (!idx->idx_expression->sameAs(node, true))
while (!idx->idx_expression_node->sameAs(node, true))
{
const auto derivedExpr = nodeAs<DerivedExprNode>(node);
const auto cast = nodeAs<CastNode>(node);
@ -804,7 +804,7 @@ bool Retrieval::checkIndexExpression(const index_desc* idx, ValueExprNode* node)
// Check the index for matching both the given stream and the given expression tree
return idx->idx_expression->containsStream(0, true) &&
return idx->idx_expression_node->containsStream(0, true) &&
node->containsStream(stream, true);
}
@ -1573,7 +1573,7 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
{
// If index condition matches the boolean, this should not be
// considered a match. Full index scan will be used instead.
if (idx->idx_condition->sameAs(boolean, true))
if (idx->idx_condition_node->sameAs(boolean, true))
return false;
}