@@ -1148,16 +1148,15 @@ static const deferred_task task_table[] =
11481148 { dfw_delete_field, delete_field },
11491149 { dfw_modify_field, modify_field },
11501150 { dfw_delete_global, delete_global },
1151- { dfw_commit_relation, commit_relation },
11521151 { dfw_create_relation, create_relation },
11531152 { dfw_delete_relation, delete_relation },
11541153 { dfw_compute_security, compute_security },
11551154 { dfw_create_index, create_index },
11561155 { dfw_grant, grant_privileges },
11571156 { dfw_create_trigger, create_trigger },
1158- /*
1159- { dfw_delete_trigger, delete_trigger },
11601157 { dfw_modify_trigger, modify_trigger },
1158+ { dfw_delete_trigger, delete_trigger },
1159+ /*
11611160 { dfw_drop_package_header, drop_package_header }, // packages should be before procedures
11621161 { dfw_modify_package_header, modify_package_header }, // packages should be before procedures
11631162 { dfw_drop_package_body, drop_package_body }, // packages should be before procedures
@@ -1185,6 +1184,7 @@ static const deferred_task task_table[] =
11851184 { dfw_set_linger, set_linger },
11861185 { dfw_clear_cache, clear_cache },
11871186 { dfw_change_repl_state, change_repl_state },
1187+ { dfw_commit_relation, commit_relation },
11881188 { dfw_null, NULL }
11891189};
11901190
@@ -3865,6 +3865,31 @@ static bool delete_global(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd
38653865}
38663866
38673867
3868+ static void triggerCommitRollback(thread_db* tdbb, USHORT id, bool doCommit)
3869+ {
3870+ switch (id & TRIGGER_TYPE_MASK) // id is RDB$TRIGGER_TYPE truncated to USHORT
3871+ {
3872+ case TRIGGER_TYPE_DB:
3873+ case TRIGGER_TYPE_DDL:
3874+ {
3875+ auto* triggersSet = MetadataCache::get(tdbb)->getTriggersSet(tdbb, id);
3876+ fb_assert(triggersSet);
3877+ if (triggersSet)
3878+ {
3879+ if (doCommit)
3880+ triggersSet->commit(tdbb);
3881+ else
3882+ triggersSet->rollback(tdbb);
3883+ }
3884+ }
3885+ break;
3886+
3887+ case TRIGGER_TYPE_DML:
3888+ break;
3889+ }
3890+ }
3891+
3892+
38683893static bool create_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
38693894{
38703895/**************************************
@@ -3882,6 +3907,10 @@ static bool create_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
38823907
38833908 switch (phase)
38843909 {
3910+ case 0:
3911+ triggerCommitRollback(tdbb, work->dfw_id, false);
3912+ break;
3913+
38853914 case 1:
38863915 case 2:
38873916 return true;
@@ -3899,21 +3928,196 @@ static bool create_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
38993928 return true;
39003929
39013930 case 7:
3902- switch (work->dfw_id & TRIGGER_TYPE_MASK) // AP: dfw_id is RDB$TRIGGER_TYPE truncated to USHORT
3931+ triggerCommitRollback(tdbb, work->dfw_id, true);
3932+ break;
3933+ }
3934+
3935+ return false;
3936+ }
3937+
3938+
3939+ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
3940+ {
3941+ /**************************************
3942+ *
3943+ * m o d i f y _ t r i g g e r
3944+ *
3945+ **************************************
3946+ *
3947+ * Functional description
3948+ * Perform required actions when modifying trigger.
3949+ *
3950+ **************************************/
3951+
3952+ SET_TDBB(tdbb);
3953+ Database* dbb = tdbb->getDatabase();
3954+ Attachment* attachment = tdbb->getAttachment();
3955+
3956+ switch (phase)
3957+ {
3958+ case 0:
3959+ triggerCommitRollback(tdbb, work->dfw_id, false);
3960+ break;
3961+
3962+ case 1:
3963+ case 2:
3964+ return true;
3965+
3966+ case 3:
39033967 {
3904- case TRIGGER_TYPE_DB:
3905- case TRIGGER_TYPE_DDL:
3968+ bool compile = !work->findArg(dfw_arg_check_blr);
3969+
3970+ // get rid of old dependencies, bring in the new
3971+ MET_delete_dependencies(tdbb, work->dfw_name, obj_trigger, transaction);
3972+ get_trigger_dependencies(work, compile, transaction);
3973+ }
3974+ return true;
3975+
3976+ case 4:
3977+ { // scope
3978+ const DeferredWork* arg = work->findArg(dfw_arg_check_blr);
3979+ if (arg)
39063980 {
3907- auto* triggersSet = MetadataCache::get(tdbb)->getTriggersSet(tdbb, work->dfw_id);
3908- fb_assert(triggersSet);
3909- if (triggersSet)
3910- triggersSet->commit(tdbb);
3981+ const MetaName relation_name(arg->dfw_name);
3982+ fb_assert(relation_name.hasData());
3983+
3984+ auto* relation = MetadataCache::lookupRelation(tdbb, relation_name, 0);
3985+ fb_assert(relation); // must be scanned earlier
3986+ if (relation)
3987+ {
3988+ AutoSetRestore2<jrd_tra*, thread_db> tempTrans(tdbb,
3989+ &thread_db::getTransaction,
3990+ &thread_db::setTransaction,
3991+ transaction);
3992+ relation->tagForUpdate(tdbb);
3993+ DFW_post_work(transaction, dfw_commit_relation, nullptr, relation->getId());
3994+ }
39113995 }
3912- break;
3996+ } // scope
3997+ return true;
39133998
3914- case TRIGGER_TYPE_DML:
3915- break;
3916- }
3999+ case 5:
4000+ { // scope
4001+ const DeferredWork* arg = work->findArg(dfw_arg_check_blr);
4002+ if (arg)
4003+ {
4004+ const MetaName relation_name(arg->dfw_name);
4005+ fb_assert(relation_name.hasData());
4006+ SSHORT valid_blr = FALSE;
4007+
4008+ try
4009+ {
4010+ auto* relation = MetadataCache::lookupRelation(tdbb, relation_name, 0);
4011+ fb_assert(relation); // must be scanned earlier
4012+
4013+ if (relation)
4014+ {
4015+ if (relation->isAvailable(tdbb) == Cached::Relation::MODIFIED)
4016+ relation->commit(tdbb);
4017+
4018+ auto* rel = relation->getObject(tdbb, 0);
4019+
4020+ MemoryPool* new_pool = dbb->createPool(ALLOC_ARGS0);
4021+ TrigArray triggers(*new_pool);
4022+
4023+ try
4024+ {
4025+ Jrd::ContextPoolHolder context(tdbb, new_pool);
4026+
4027+ MET_load_trigger(tdbb, rel, work->dfw_name,
4028+ [&triggers](int t)->Triggers& {return triggers[t];});
4029+
4030+ for (int i = 1; i < TRIGGER_MAX; ++i)
4031+ {
4032+ if (triggers[i])
4033+ {
4034+ for (auto t : triggers[i])
4035+ t->compile(tdbb);
4036+
4037+ triggers[i].release(tdbb, true);
4038+ }
4039+ }
4040+
4041+ valid_blr = TRUE;
4042+ }
4043+ catch (const Firebird::Exception&)
4044+ {
4045+ dbb->deletePool(new_pool);
4046+ throw;
4047+ }
4048+
4049+ dbb->deletePool(new_pool);
4050+ }
4051+ }
4052+ catch (const Firebird::Exception&)
4053+ {
4054+ }
4055+
4056+ AutoCacheRequest request(tdbb, irq_trg_validate, IRQ_REQUESTS);
4057+
4058+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
4059+ TRG IN RDB$TRIGGERS WITH
4060+ TRG.RDB$TRIGGER_NAME EQ work->dfw_name.c_str() AND TRG.RDB$TRIGGER_BLR NOT MISSING
4061+ {
4062+ MODIFY TRG USING
4063+ TRG.RDB$VALID_BLR = valid_blr;
4064+ TRG.RDB$VALID_BLR.NULL = FALSE;
4065+ END_MODIFY
4066+ }
4067+ END_FOR
4068+ }
4069+ } // scope
4070+ return true;
4071+
4072+ case 6:
4073+ return true;
4074+
4075+ case 7:
4076+ triggerCommitRollback(tdbb, work->dfw_id, true);
4077+ break;
4078+ }
4079+
4080+ return false;
4081+ }
4082+
4083+
4084+ static bool delete_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
4085+ {
4086+ /**************************************
4087+ *
4088+ * d e l e t e _ t r i g g e r
4089+ *
4090+ **************************************
4091+ *
4092+ * Functional description
4093+ * Cleanup after a deleted trigger.
4094+ *
4095+ **************************************/
4096+
4097+ SET_TDBB(tdbb);
4098+
4099+ switch (phase)
4100+ {
4101+ case 0:
4102+ triggerCommitRollback(tdbb, work->dfw_id, false);
4103+ break;
4104+
4105+ case 1:
4106+ case 2:
4107+ return true;
4108+
4109+ case 3:
4110+ // get rid of dependencies
4111+ MET_delete_dependencies(tdbb, work->dfw_name, obj_trigger, transaction);
4112+ return true;
4113+
4114+ case 4:
4115+ case 5:
4116+ case 6:
4117+ return true;
4118+
4119+ case 7:
4120+ triggerCommitRollback(tdbb, work->dfw_id, true);
39174121 break;
39184122 }
39194123
0 commit comments