diff --git a/src/jrd/dfw.epp b/src/jrd/dfw.epp index 41242cd5d3..8e2bf8229f 100644 --- a/src/jrd/dfw.epp +++ b/src/jrd/dfw.epp @@ -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) diff --git a/src/jrd/dfw_proto.h b/src/jrd/dfw_proto.h index f630f88674..5205e9867d 100644 --- a/src/jrd/dfw_proto.h +++ b/src/jrd/dfw_proto.h @@ -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 diff --git a/src/jrd/tra.h b/src/jrd/tra.h index 9f5d7849b5..2c9820bd7a 100644 --- a/src/jrd/tra.h +++ b/src/jrd/tra.h @@ -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 diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index b5f32da24f..f86fe647d4 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -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))) {