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

Fixed two DFW bugs

1. Unregistered FB2 bug - expression index dependencies was tracked not correctly.
2. SF #1250150
This commit is contained in:
hvlad 2005-08-02 11:41:37 +00:00
parent 39da9e362f
commit c104f1b23d
4 changed files with 70 additions and 18 deletions

View File

@ -167,9 +167,6 @@ static bool add_difference(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool delete_difference(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool begin_backup(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool end_backup(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static Lock* protect_relation(thread_db*, jrd_tra*, jrd_rel*, bool&);
static void release_protect_lock(thread_db*, jrd_tra*, Lock*);
static void check_partners(thread_db*, const USHORT);
/* ---------------------------------------------------------------- */
@ -193,6 +190,10 @@ static void setup_trigger_details(thread_db*, jrd_rel*, blb*, trig_vec**, const
const TEXT*, bool);
static bool validate_text_type (thread_db*, const TemporaryField*);
static Lock* protect_relation(thread_db*, jrd_tra*, jrd_rel*, bool&);
static void release_protect_lock(thread_db*, jrd_tra*, Lock*);
static void check_partners(thread_db*, const USHORT);
static const UCHAR nonnull_validation_blr[] =
{
blr_version5,
@ -213,6 +214,7 @@ static const deferred_task task_table[] =
{ dfw_add_file, add_file },
{ dfw_add_shadow, add_shadow },
{ dfw_delete_index, delete_index },
{ dfw_delete_expression_index, delete_index },
{ dfw_delete_rfr, delete_rfr },
{ dfw_delete_relation, delete_relation },
{ dfw_delete_shadow, delete_shadow },
@ -226,7 +228,6 @@ static const deferred_task task_table[] =
#ifdef EXPRESSION_INDICES
{ dfw_create_expression_index, PCMET_expression_index },
#endif
{ dfw_delete_expression_index, delete_index },
{ dfw_grant, GRANT_privileges },
{ dfw_create_trigger, create_trigger },
{ dfw_delete_trigger, delete_trigger },
@ -637,7 +638,7 @@ DeferredWork* DFW_post_work(jrd_tra* transaction, enum dfw_t type, const dsc* de
}
void DFW_post_work_arg( jrd_tra* transaction, DeferredWork* work, const dsc* desc,
DeferredWork* DFW_post_work_arg( jrd_tra* transaction, DeferredWork* work, const dsc* desc,
USHORT id)
{
/**************************************
@ -651,7 +652,7 @@ void DFW_post_work_arg( jrd_tra* transaction, DeferredWork* work, const dsc* des
*
**************************************/
post_work(transaction,
return post_work(transaction,
work->dfw_sav_number,
&work->dfw_args,
work->dfw_type,
@ -2443,18 +2444,36 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work,
IDX_delete_index(tdbb, relation, id);
if (work->dfw_type == dfw_delete_expression_index)
{
// for expression index there are dependincies
// therefore work->dfw_args was set in VIO_erase
// to let us know that expression index name
fb_assert(work->dfw_args);
const DeferredWork* arg = work->dfw_args;
while(arg && (arg->dfw_type != dfw_arg_index_name))
{
arg = arg->dfw_next;
}
fb_assert(arg);
MET_delete_dependencies(tdbb,
work->dfw_name,
arg->dfw_name,
obj_expression_index);
}
// if index was bound to deleted FK constraint
// then work->dfw_args was set in VIO_erase
if (work->dfw_args) {
if (work->dfw_args->dfw_id) {
const DeferredWork* arg = work->dfw_args;
while(arg && (arg->dfw_type != dfw_arg_partner_rel_id))
{
arg = arg->dfw_next;
}
if (arg) {
if (arg->dfw_id) {
check_partners(tdbb, relation->rel_id);
if (relation->rel_id != work->dfw_args->dfw_id) {
check_partners(tdbb, work->dfw_args->dfw_id);
if (relation->rel_id != arg->dfw_id) {
check_partners(tdbb, arg->dfw_id);
}
}
else {
@ -3136,7 +3155,7 @@ static bool find_depend_in_dfw( thread_db* tdbb,
dfw_type = dfw_delete_procedure;
break;
case obj_expression_index:
dfw_type = dfw_delete_index;
dfw_type = dfw_delete_expression_index;
break;
default:
fb_assert(false);
@ -3154,6 +3173,21 @@ static bool find_depend_in_dfw( thread_db* tdbb,
{
return true;
}
if (work->dfw_type == dfw_type &&
dfw_type == dfw_delete_expression_index)
{
const DeferredWork* arg = work->dfw_args;
while (arg)
{
if (arg->dfw_type == dfw_arg_index_name &&
arg->dfw_name == object_name)
{
return true;
}
arg = arg->dfw_next;
}
}
}
if (dfw_type == dfw_delete_global)

View File

@ -31,7 +31,7 @@ void DFW_perform_system_work(void);
void DFW_perform_work(Jrd::jrd_tra*);
void DFW_perform_post_commit_work(Jrd::jrd_tra*);
Jrd::DeferredWork* DFW_post_work(Jrd::jrd_tra*, enum Jrd::dfw_t, const dsc*, USHORT);
void DFW_post_work_arg(Jrd::jrd_tra*, Jrd::DeferredWork*, const dsc*, USHORT);
Jrd::DeferredWork* DFW_post_work_arg(Jrd::jrd_tra*, Jrd::DeferredWork*, const dsc*, USHORT);
void DFW_update_index(const TEXT*, USHORT, const Jrd::SelectivityList&);
#endif // JRD_DFW_PROTO_H

View File

@ -244,7 +244,12 @@ enum dfw_t {
dfw_add_difference,
dfw_delete_difference,
dfw_begin_backup,
dfw_end_backup
dfw_end_backup,
// deffered works argument types
dfw_arg_index_name, // index name for dfw_delete_expression_index, mandatory
dfw_arg_partner_rel_id, // partner relation id for dfw_delete_index if index is FK, optional
dfw_arg_proc_name // procedure name for dfw_delete_prm, mandatory
};
class DeferredWork : public pool_alloc<type_dfw>

View File

@ -1327,6 +1327,12 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
{
work = DFW_post_work(transaction, dfw_delete_expression_index,
&desc, id);
// add expression index name to correctly delete dependencies
DSC idx_name;
EVL_field(0, rpb->rpb_record, f_idx_name, &idx_name);
DeferredWork* arg = DFW_post_work_arg(transaction, work, &idx_name, id);
arg->dfw_type = dfw_arg_index_name;
}
else
{
@ -1353,12 +1359,14 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
(MET_lookup_partner(tdbb, r2, &idx, idx_name)) &&
(partner = MET_lookup_relation_id(tdbb, idx.idx_primary_relation, false)) )
{
DFW_post_work_arg(transaction, work, 0, partner->rel_id);
DeferredWork* arg = DFW_post_work_arg(transaction, work, 0, partner->rel_id);
arg->dfw_type = dfw_arg_partner_rel_id;
}
else { // can't find partner relation - impossible ?
// add empty argument to let DFW know dropping
// index was bound with FK
DFW_post_work_arg(transaction, work, 0, 0);
DeferredWork* arg = DFW_post_work_arg(transaction, work, 0, 0);
arg->dfw_type = dfw_arg_partner_rel_id;
}
}
break;
@ -1385,8 +1393,13 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
MOV_get_metadata_str(&desc, procedure_name, sizeof(procedure_name));
if ( (procedure = MET_lookup_procedure(tdbb, procedure_name, true)) )
{
DFW_post_work(transaction, dfw_delete_prm, &desc2,
work = DFW_post_work(transaction, dfw_delete_prm, &desc2,
procedure->prc_id);
// procedure name to track parameter dependencies
DeferredWork* arg = DFW_post_work_arg(transaction, work, &desc,
procedure->prc_id);
arg->dfw_type = dfw_arg_proc_name;
}
EVL_field(0, rpb->rpb_record, f_prm_sname, &desc2);
DFW_post_work(transaction, dfw_delete_global, &desc2, 0);
@ -3826,13 +3839,13 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
Express interest in the relation to prevent it from being deleted
out from under us while garbage collection is in-progress. */
//hvlad: skip system relations
vec* vector = dbb->dbb_relations;
for (ULONG id = 0; vector && id < vector->count(); ++id) {
relation = (jrd_rel*) (*vector)[id];
RelationGarbage *relGarbage =
relation ? (RelationGarbage*)relation->rel_garbage : NULL;
//hvlad: skip system relations
if (relation && (relation->rel_gc_bitmap || relGarbage) &&
!(relation->rel_flags & (REL_deleted | REL_deleting | REL_system)))
{