Skip to content

Commit 0f8e19d

Browse files
committed
ALTER/DROP various TRIGGERs
1 parent 4eeea4e commit 0f8e19d

File tree

8 files changed

+292
-35
lines changed

8 files changed

+292
-35
lines changed

src/dsql/DdlNodes.epp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,6 +3059,23 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
30593059
END_MODIFY
30603060
}
30613061
END_FOR
3062+
3063+
static const CachedRequestId rq3id;
3064+
AutoCacheRequest request3(tdbb, rq3id);
3065+
3066+
FOR (REQUEST_HANDLE request3 TRANSACTION_HANDLE transaction)
3067+
P IN RDB$PROCEDURES
3068+
WITH P.RDB$PROCEDURE_NAME EQ name.c_str() AND
3069+
P.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
3070+
{
3071+
MODIFY P
3072+
{
3073+
P.RDB$PROCEDURE_INPUTS = (USHORT) parameters.getCount();
3074+
P.RDB$PROCEDURE_OUTPUTS = (USHORT) returns.getCount();
3075+
}
3076+
END_MODIFY
3077+
}
3078+
END_FOR
30623079
}
30633080

30643081
if (secondPass && modified)
@@ -3723,8 +3740,6 @@ void CreateAlterTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
37233740
{
37243741
fb_assert(create || alter);
37253742

3726-
Attachment* const attachment = transaction->getAttachment();
3727-
37283743
source.ltrim("\n\r\t ");
37293744

37303745
// run all statements under savepoint control
@@ -3737,6 +3752,9 @@ void CreateAlterTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
37373752

37383753
if (alter)
37393754
{
3755+
// DB-wide triggers are preloaded in a cache during attachDatabase(),
3756+
// i.e. no need in something like oldVersion<>() call here.
3757+
37403758
if (!modify(tdbb, dsqlScratch, transaction))
37413759
{
37423760
if (create) // create or alter
@@ -9182,6 +9200,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
91829200
}
91839201

91849202
MetadataCache::newVersion<Cached::Relation>(tdbb, rel->getId());
9203+
DFW_post_work(transaction, dfw_commit_relation, nullptr, rel->getId());
91859204

91869205
if (beforeTriggerWasExecuted)
91879206
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_TABLE, name, nullptr);

src/jrd/CacheVector.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ class ListEntry : public HazardObject
253253
if (oldVal && oldVal->isBusy(newVal->traNumber)) // modified in other transaction
254254
return false;
255255

256-
newVal->next.store(oldVal, atomics::memory_order_acquire);
256+
newVal->next.store(oldVal, atomics::memory_order_release);
257257
return list.compare_exchange_strong(oldVal, newVal, std::memory_order_release, std::memory_order_acquire);
258258
}
259259

@@ -305,7 +305,7 @@ class ListEntry : public HazardObject
305305

306306
traNumber = nextTrans;
307307
version = VersionSupport::next(tdbb);
308-
auto flags = cacheFlags.fetch_or(CacheFlag::COMMITTED);
308+
auto flags = cacheFlags.fetch_or(CacheFlag::COMMITTED); // !!!!!!!!!!!!!!!! CMPXCHG!!!
309309

310310
fb_assert((flags & CacheFlag::COMMITTED ? nextTrans : currentTrans) == oldNumber);
311311

@@ -997,8 +997,6 @@ class CacheVector : public Firebird::PermanentStorage
997997

998998
void tagForUpdate(thread_db* tdbb, MetaId id)
999999
{
1000-
auto constexpr fl = CacheFlag::NOCOMMIT | CacheFlag::NOSCAN;
1001-
10021000
fb_assert(id < getCount());
10031001
if (id < getCount())
10041002
{

src/jrd/dfw.epp

Lines changed: 218 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
38683893
static 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

Comments
 (0)