8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 07:23: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 delete_difference(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool begin_backup(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 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); const TEXT*, bool);
static bool validate_text_type (thread_db*, const TemporaryField*); 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[] = static const UCHAR nonnull_validation_blr[] =
{ {
blr_version5, blr_version5,
@ -213,6 +214,7 @@ static const deferred_task task_table[] =
{ dfw_add_file, add_file }, { dfw_add_file, add_file },
{ dfw_add_shadow, add_shadow }, { dfw_add_shadow, add_shadow },
{ dfw_delete_index, delete_index }, { dfw_delete_index, delete_index },
{ dfw_delete_expression_index, delete_index },
{ dfw_delete_rfr, delete_rfr }, { dfw_delete_rfr, delete_rfr },
{ dfw_delete_relation, delete_relation }, { dfw_delete_relation, delete_relation },
{ dfw_delete_shadow, delete_shadow }, { dfw_delete_shadow, delete_shadow },
@ -226,7 +228,6 @@ static const deferred_task task_table[] =
#ifdef EXPRESSION_INDICES #ifdef EXPRESSION_INDICES
{ dfw_create_expression_index, PCMET_expression_index }, { dfw_create_expression_index, PCMET_expression_index },
#endif #endif
{ dfw_delete_expression_index, delete_index },
{ dfw_grant, GRANT_privileges }, { dfw_grant, GRANT_privileges },
{ dfw_create_trigger, create_trigger }, { dfw_create_trigger, create_trigger },
{ dfw_delete_trigger, delete_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) 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_sav_number,
&work->dfw_args, &work->dfw_args,
work->dfw_type, work->dfw_type,
@ -2443,18 +2444,36 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work,
IDX_delete_index(tdbb, relation, id); IDX_delete_index(tdbb, relation, id);
if (work->dfw_type == dfw_delete_expression_index) 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, MET_delete_dependencies(tdbb,
work->dfw_name, arg->dfw_name,
obj_expression_index); obj_expression_index);
} }
// if index was bound to deleted FK constraint // if index was bound to deleted FK constraint
// then work->dfw_args was set in VIO_erase // then work->dfw_args was set in VIO_erase
if (work->dfw_args) { const DeferredWork* arg = work->dfw_args;
if (work->dfw_args->dfw_id) { 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); check_partners(tdbb, relation->rel_id);
if (relation->rel_id != work->dfw_args->dfw_id) { if (relation->rel_id != arg->dfw_id) {
check_partners(tdbb, work->dfw_args->dfw_id); check_partners(tdbb, arg->dfw_id);
} }
} }
else { else {
@ -3136,7 +3155,7 @@ static bool find_depend_in_dfw( thread_db* tdbb,
dfw_type = dfw_delete_procedure; dfw_type = dfw_delete_procedure;
break; break;
case obj_expression_index: case obj_expression_index:
dfw_type = dfw_delete_index; dfw_type = dfw_delete_expression_index;
break; break;
default: default:
fb_assert(false); fb_assert(false);
@ -3154,6 +3173,21 @@ static bool find_depend_in_dfw( thread_db* tdbb,
{ {
return true; 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) 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_work(Jrd::jrd_tra*);
void DFW_perform_post_commit_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); 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&); void DFW_update_index(const TEXT*, USHORT, const Jrd::SelectivityList&);
#endif // JRD_DFW_PROTO_H #endif // JRD_DFW_PROTO_H

View File

@ -244,7 +244,12 @@ enum dfw_t {
dfw_add_difference, dfw_add_difference,
dfw_delete_difference, dfw_delete_difference,
dfw_begin_backup, 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> 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, work = DFW_post_work(transaction, dfw_delete_expression_index,
&desc, id); &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 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)) && (MET_lookup_partner(tdbb, r2, &idx, idx_name)) &&
(partner = MET_lookup_relation_id(tdbb, idx.idx_primary_relation, false)) ) (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 ? else { // can't find partner relation - impossible ?
// add empty argument to let DFW know dropping // add empty argument to let DFW know dropping
// index was bound with FK // 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; 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)); MOV_get_metadata_str(&desc, procedure_name, sizeof(procedure_name));
if ( (procedure = MET_lookup_procedure(tdbb, procedure_name, true)) ) 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->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); EVL_field(0, rpb->rpb_record, f_prm_sname, &desc2);
DFW_post_work(transaction, dfw_delete_global, &desc2, 0); 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 Express interest in the relation to prevent it from being deleted
out from under us while garbage collection is in-progress. */ out from under us while garbage collection is in-progress. */
//hvlad: skip system relations
vec* vector = dbb->dbb_relations; vec* vector = dbb->dbb_relations;
for (ULONG id = 0; vector && id < vector->count(); ++id) { for (ULONG id = 0; vector && id < vector->count(); ++id) {
relation = (jrd_rel*) (*vector)[id]; relation = (jrd_rel*) (*vector)[id];
RelationGarbage *relGarbage = RelationGarbage *relGarbage =
relation ? (RelationGarbage*)relation->rel_garbage : NULL; relation ? (RelationGarbage*)relation->rel_garbage : NULL;
//hvlad: skip system relations
if (relation && (relation->rel_gc_bitmap || relGarbage) && if (relation && (relation->rel_gc_bitmap || relGarbage) &&
!(relation->rel_flags & (REL_deleted | REL_deleting | REL_system))) !(relation->rel_flags & (REL_deleted | REL_deleting | REL_system)))
{ {