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