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:
parent
2bbfd526b5
commit
fda52dd662
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user