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

Fixed crash if the index is created as both computed and partial (see example in #7257). Better resource cleanup on error. Remove redundant ODS checks.

This commit is contained in:
Dmitry Yemanov 2023-02-17 19:05:38 +03:00
parent 340466e0df
commit 8f12020e25
2 changed files with 82 additions and 80 deletions

View File

@ -2717,7 +2717,6 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
{
jrd_rel* relation = nullptr;
CompilerScratch* csb = nullptr;
MemoryPool* new_pool = nullptr;
const auto dbb = tdbb->getDatabase();
const auto attachment = tdbb->getAttachment();
@ -2776,67 +2775,72 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
MET_scan_relation(tdbb, relation);
// Allocate a new pool to contain the expression tree
// for index expression / condition
new_pool = attachment->createPool();
// for index expression
const auto new_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, new_pool);
try
{
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$EXPRESSION_BLR,
nullptr, &csb, work->dfw_name, obj_index_expression, 0,
transaction);
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$EXPRESSION_BLR,
nullptr, &csb, work->dfw_name, obj_index_expression, 0,
transaction);
idx.idx_expression_statement = Statement::makeValueExpression(tdbb,
idx.idx_expression, idx.idx_expression_desc, csb, false);
idx.idx_expression_statement = Statement::makeValueExpression(tdbb,
idx.idx_expression, idx.idx_expression_desc, csb, false);
// fake a description of the index
// fake a description of the index
idx.idx_count = 1;
idx.idx_flags |= idx_expression;
idx.idx_rpt[0].idx_itype =
DFW_assign_index_type(tdbb, work->dfw_name,
idx.idx_expression_desc.dsc_dtype,
idx.idx_expression_desc.dsc_sub_type);
idx.idx_rpt[0].idx_selectivity = 0;
idx.idx_count = 1;
idx.idx_flags |= idx_expression;
idx.idx_rpt[0].idx_itype =
DFW_assign_index_type(tdbb, work->dfw_name,
idx.idx_expression_desc.dsc_dtype,
idx.idx_expression_desc.dsc_sub_type);
idx.idx_rpt[0].idx_selectivity = 0;
}
catch (const Exception&)
{
attachment->deletePool(new_pool);
throw;
}
if (!IDX.RDB$CONDITION_BLR.NULL)
{
// Allocate a new pool to contain the expression tree
// for index condition
const auto new_pool = attachment->createPool();
try
{
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$CONDITION_BLR,
nullptr, &csb, work->dfw_name, obj_index_condition, 0,
transaction);
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
idx.idx_condition, csb, false);
idx.idx_flags |= idx_condition;
}
catch (const Exception&)
{
attachment->deletePool(new_pool);
throw;
}
}
}
}
END_FOR
if (!relation)
{
if (new_pool)
attachment->deletePool(new_pool);
// Msg308: can't create index %s
ERR_post(Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_idx_create_err) << Arg::Str(work->dfw_name));
}
idx.idx_condition = nullptr;
idx.idx_condition_statement = nullptr;
if (dbb->getEncodedOdsVersion() >= ODS_13_1)
{
AutoCacheRequest request(tdbb, irq_c_cond_index, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request)
IDX IN RDB$INDICES WITH
IDX.RDB$CONDITION_BLR NOT MISSING AND
IDX.RDB$INDEX_NAME EQ work->dfw_name.c_str()
{
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$CONDITION_BLR,
nullptr, &csb, work->dfw_name, obj_index_condition, 0,
transaction);
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
idx.idx_condition, csb, false);
idx.idx_flags |= idx_condition;
}
END_FOR
}
delete csb;
// Actually create the index
@ -3481,6 +3485,38 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
}
END_FOR
idx.idx_condition = nullptr;
idx.idx_condition_statement = nullptr;
if (!IDX.RDB$CONDITION_BLR.NULL)
{
// Allocate a new pool to contain the expression tree
// for index condition
const auto new_pool = attachment->createPool();
CompilerScratch* csb = nullptr;
try
{
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$CONDITION_BLR,
nullptr, &csb, work->dfw_name, obj_index_condition, 0,
transaction);
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
idx.idx_condition, csb, false);
idx.idx_flags |= idx_condition;
}
catch (const Exception&)
{
attachment->deletePool(new_pool);
throw;
}
delete csb;
}
// Here we need dirty reads from database (first of all from
// RDB$RELATION_FIELDS and RDB$FIELDS - tables not directly related
// with index to be created and it's dfw_name). Missing it breaks gbak,
@ -3578,39 +3614,6 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
// Msg308: can't create index %s
}
idx.idx_condition = nullptr;
idx.idx_condition_statement = nullptr;
if (dbb->getEncodedOdsVersion() >= ODS_13_1)
{
// Allocate a new pool to contain the expression tree
// for index condition
const auto new_pool = attachment->createPool();
CompilerScratch* csb = nullptr;
AutoCacheRequest request(tdbb, irq_c_cond_index, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request)
IDX IN RDB$INDICES WITH
IDX.RDB$CONDITION_BLR NOT MISSING AND
IDX.RDB$INDEX_NAME EQ work->dfw_name.c_str()
{
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$CONDITION_BLR,
nullptr, &csb, work->dfw_name, obj_index_condition, 0,
transaction);
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
idx.idx_condition, csb, false);
idx.idx_flags |= idx_condition;
}
END_FOR
delete csb;
}
// Actually create the index
partner_relation = NULL;

View File

@ -85,7 +85,6 @@ enum irq_type_t
irq_c_exp_index, // create expression index
irq_l_exp_index, // lookup expression index
irq_l_exp_index_blr, // lookup expression index BLR
irq_c_cond_index, // create condition index
irq_l_cond_index, // lookup condition index
irq_l_rel_id, // lookup relation id