8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 22:43:03 +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 END_FOR
idx.idx_condition = nullptr; idx.idx_condition_node = nullptr;
idx.idx_condition_statement = nullptr; idx.idx_condition_statement = nullptr;
if (!IDX.RDB$CONDITION_BLR.NULL) if (!IDX.RDB$CONDITION_BLR.NULL)
@ -10849,7 +10849,7 @@ MetaId StoreIndexNode::create(thread_db* tdbb, Cached::Relation* rel, jrd_tra* t
transaction); transaction);
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb, idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
idx.idx_condition, csb, false); idx.idx_condition_node, csb, false);
idx.idx_flags |= idx_condition; idx.idx_flags |= idx_condition;
} }
@ -11114,7 +11114,7 @@ MetaId StoreIndexNode::createExpression(thread_db* tdbb, Cached::Relation* rel,
transaction); transaction);
idx.idx_expression_statement = Statement::makeValueExpression(tdbb, 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 // fake a description of the index
@ -11147,7 +11147,7 @@ MetaId StoreIndexNode::createExpression(thread_db* tdbb, Cached::Relation* rel,
transaction); transaction);
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb, idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
idx.idx_condition, csb, false); idx.idx_condition_node, csb, false);
idx.idx_flags |= idx_condition; idx.idx_flags |= idx_condition;
} }

View File

@ -551,6 +551,18 @@ IndexVersion::IndexVersion(MemoryPool& p, Cached::Index* idp)
: perm(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) void jrd_rel::releaseTriggers(thread_db* tdbb, bool destroy)
{ {
for (int n = 1; n < TRIGGER_MAX; ++n) for (int n = 1; n < TRIGGER_MAX; ++n)

View File

@ -512,10 +512,7 @@ public:
return FB_NEW_POOL(p) IndexVersion(p, idp); return FB_NEW_POOL(p) IndexVersion(p, idp);
} }
static void destroy(thread_db* tdbb, IndexVersion* idv) static void destroy(thread_db* tdbb, IndexVersion* idv);
{
delete idv;
}
static Lock* makeLock(thread_db* tdbb, MemoryPool& p) 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_foreign_deps = nullptr;
idx->idx_primary_relation = 0; idx->idx_primary_relation = 0;
idx->idx_primary_index = 0; idx->idx_primary_index = 0;
idx->idx_expression = nullptr; idx->idx_expression_node = nullptr;
idx->idx_expression_statement = nullptr; idx->idx_expression_statement = nullptr;
idx->idx_condition = nullptr; idx->idx_condition_node = nullptr;
idx->idx_condition_statement = nullptr; idx->idx_condition_statement = nullptr;
idx->idx_fraction = 1.0; 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) if (idx->idx_flags & idx_expression)
{ {
MET_lookup_index_expression(tdbb, relation, idx); MET_lookup_index_expression(tdbb, relation, idx);
fb_assert(idx->idx_expression); fb_assert(idx->idx_expression_node);
} }
if (idx->idx_flags & idx_condition) if (idx->idx_flags & idx_condition)
{ {
MET_lookup_index_condition(tdbb, relation, idx); MET_lookup_index_condition(tdbb, relation, idx);
fb_assert(idx->idx_condition); fb_assert(idx->idx_condition_node);
} }
return true; 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)) if (!(idx->idx_flags & idx_condition))
return true; return true;
fb_assert(idx->idx_condition); fb_assert(idx->idx_condition_node);
Request* const orgRequest = tdbb->getRequest(); Request* const orgRequest = tdbb->getRequest();
Request* const conditionRequest = idx->idx_condition_statement->findRequest(tdbb); 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 else
conditionRequest->validateTimeStamp(); conditionRequest->validateTimeStamp();
result = idx->idx_condition->execute(tdbb, conditionRequest); result = idx->idx_condition_node->execute(tdbb, conditionRequest);
} }
catch (const Exception& ex) 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) DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& notNull)
{ {
SET_TDBB(tdbb); SET_TDBB(tdbb);
fb_assert(idx->idx_expression); fb_assert(idx->idx_expression_node);
// check for recursive expression evaluation // check for recursive expression evaluation
Request* const org_request = tdbb->getRequest(); Request* const org_request = tdbb->getRequest();
@ -871,7 +871,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool&
else else
expr_request->validateTimeStamp(); 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; result = &idx->idx_expression_desc;
notNull = !(expr_request->req_flags & req_null); 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: default:
if (idx->idx_flags & idx_expression) if (idx->idx_flags & idx_expression)
{ {
fb_assert(idx->idx_expression); fb_assert(idx->idx_expression_node);
length = idx->idx_expression_desc.dsc_length; length = idx->idx_expression_desc.dsc_length;
if (idx->idx_expression_desc.dsc_dtype == dtype_varying) 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 MetaId idx_primary_relation; // id for primary key partner relation
USHORT idx_count; // number of keys USHORT idx_count; // number of keys
ForeignDeps* idx_foreign_deps; // foreign key partners 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 dsc idx_expression_desc; // descriptor for expression result
Statement* idx_expression_statement; // stored statement for expression evaluation 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 Statement* idx_condition_statement; // stored statement for index condition
float idx_fraction; // fraction of keys included in the index float idx_fraction; // fraction of keys included in the index
// This structure should exactly match IRTD structure for current ODS // This structure should exactly match IRTD structure for current ODS

View File

@ -389,7 +389,7 @@ public:
m_idx = *creation->index; // copy m_idx = *creation->index; // copy
if (m_ownAttach) if (m_ownAttach)
{ {
m_idx.idx_expression = NULL; m_idx.idx_expression_node = NULL;
m_idx.idx_expression_statement = NULL; m_idx.idx_expression_statement = NULL;
m_idx.idx_foreign_deps = NULL; m_idx.idx_foreign_deps = NULL;
} }
@ -546,14 +546,14 @@ bool IndexCreateTask::handler(WorkItem& _item)
partner_index_id = idx->idx_primary_index; 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()); fb_assert(!m_exprBlob.isEmpty());
CompilerScratch* csb = NULL; CompilerScratch* csb = NULL;
Jrd::ContextPoolHolder context(tdbb, dbb->createPool(ALLOC_ARGS0)); 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)); &csb, &idx->idx_expression_statement, false, false));
delete csb; 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); IndexVersion* idv = relation->lookup_index(tdbb, idx->idx_id, CacheFlag::AUTOCREATE);
if (idv) if (idv)
{ {
idx->idx_condition = idv->idv_condition; idx->idx_condition_node = idv->idv_condition;
idx->idx_condition_statement = idv->idv_condition_statement; 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); IndexVersion* idv = relation->lookup_index(tdbb, idx->idx_id, CacheFlag::AUTOCREATE);
if (idv) if (idv)
{ {
idx->idx_expression = idv->idv_expression; idx->idx_expression_node = idv->idv_expression;
idx->idx_expression_statement = idv->idv_expression_statement; idx->idx_expression_statement = idv->idv_expression_statement;
memcpy(&idx->idx_expression_desc, &idv->idv_expression_desc, sizeof(struct dsc)); 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()) ? auto* relation = (expression.hasData() || condition.hasData()) ?
MetadataCache::lookupRelation(tdbb, relId, CacheFlag::AUTOCREATE) : nullptr; MetadataCache::lookupRelation(tdbb, relId, CacheFlag::AUTOCREATE) : nullptr;
perm->createLock(tdbb, relId, getId()); perm->createLock(tdbb, relId, getId());
// ????? perm->createLock( caching lock // ?????????????? perm->createLock( caching lock
if (expression.hasData()) if (expression.hasData())
{ {

View File

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