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

Reimplement system triggers in C++/GDML code.

This commit is contained in:
Adriano dos Santos Fernandes 2024-08-01 22:44:08 -03:00
parent 2c48a4ed06
commit 9926ab88b4
23 changed files with 1532 additions and 1982 deletions

View File

@ -31,6 +31,7 @@
<ClCompile Include="..\..\..\gen\jrd\ini.cpp" />
<ClCompile Include="..\..\..\gen\jrd\met.cpp" />
<ClCompile Include="..\..\..\gen\jrd\scl.cpp" />
<ClCompile Include="..\..\..\gen\jrd\SystemTriggers.cpp" />
<ClCompile Include="..\..\..\gen\utilities\gstat\dba.cpp" />
<ClCompile Include="..\..\..\src\dsql\AggNodes.cpp" />
<ClCompile Include="..\..\..\src\dsql\BlrDebugWriter.cpp" />
@ -350,6 +351,7 @@
<ClInclude Include="..\..\..\src\jrd\sys-packages\SqlPackage.h" />
<ClInclude Include="..\..\..\src\jrd\SysFunction.h" />
<ClInclude Include="..\..\..\src\jrd\SystemPackages.h" />
<ClInclude Include="..\..\..\src\jrd\SystemTriggers.h" />
<ClInclude Include="..\..\..\src\jrd\TempSpace.h" />
<ClInclude Include="..\..\..\src\jrd\TimeZone.h" />
<ClInclude Include="..\..\..\src\jrd\tpc_proto.h" />
@ -390,6 +392,7 @@
<None Include="..\..\..\src\jrd\ini.epp" />
<None Include="..\..\..\src\jrd\met.epp" />
<None Include="..\..\..\src\jrd\scl.epp" />
<None Include="..\..\..\src\jrd\SystemTriggers.epp" />
<None Include="..\..\..\src\utilities\gstat\dba.epp" />
</ItemGroup>
<PropertyGroup Label="Globals">

View File

@ -423,6 +423,9 @@
<ClCompile Include="..\..\..\gen\jrd\scl.cpp">
<Filter>JRD files\GPRE cpp</Filter>
</ClCompile>
<ClCompile Include="..\..\..\gen\jrd\SystemTriggers.cpp">
<Filter>JRD files\GPRE cpp</Filter>
</ClCompile>
<ClCompile Include="..\..\..\gen\jrd\dfw.cpp">
<Filter>JRD files\GPRE cpp</Filter>
</ClCompile>
@ -1085,6 +1088,9 @@
<ClInclude Include="..\..\..\src\jrd\SystemPackages.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\SystemTriggers.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\Coercion.h">
<Filter>Header files</Filter>
</ClInclude>
@ -1139,6 +1145,9 @@
<None Include="..\..\..\src\jrd\scl.epp">
<Filter>JRD files\GPRE files</Filter>
</None>
<None Include="..\..\..\src\jrd\SystemTriggers.epp">
<Filter>JRD files\GPRE files</Filter>
</None>
<None Include="..\..\..\src\utilities\gstat\dba.epp">
<Filter>Services</Filter>
</None>

View File

@ -78,7 +78,7 @@ goto :EOF
@for %%i in (metd) do @call :PREPROCESS dsql %%i -gds_cxx
@for %%i in (DdlNodes, PackageNodes) do @call :PREPROCESS dsql %%i -gds_cxx
@for %%i in (gpre_meta) do @call :PREPROCESS gpre/std %%i
@for %%i in (dfw, dpm, dyn_util, fun, grant, ini, met, scl, Function) do @call :PREPROCESS jrd %%i -gds_cxx
@for %%i in (dfw, dpm, dyn_util, fun, grant, ini, met, scl, Function, SystemTriggers) do @call :PREPROCESS jrd %%i -gds_cxx
@for %%i in (extract, isql, show) do @call :PREPROCESS isql %%i -ocxx
@for %%i in (dba) do @call :PREPROCESS utilities/gstat %%i
@for %%i in (stats) do @call :PREPROCESS utilities %%i

View File

@ -2781,7 +2781,7 @@ const StmtNode* EraseNode::erase(thread_db* tdbb, Request* request, WhichTrigger
spPreTriggers.release();
// Handle post operation trigger.
if (relation->rel_post_erase && whichTrig != PRE_TRIG)
if ((relation->rel_post_erase || relation->isSystem()) && whichTrig != PRE_TRIG)
{
EXE_execute_triggers(tdbb, &relation->rel_post_erase, rpb, NULL, TRIGGER_DELETE, POST_TRIG);
}
@ -7848,7 +7848,7 @@ const StmtNode* ModifyNode::modify(thread_db* tdbb, Request* request, WhichTrigg
newRpb->rpb_number = orgRpb->rpb_number;
newRpb->rpb_number.setValid(true);
if (relation->rel_post_modify && whichTrig != PRE_TRIG)
if ((relation->rel_post_modify || relation->isSystem()) && whichTrig != PRE_TRIG)
{
EXE_execute_triggers(tdbb, &relation->rel_post_modify, orgRpb, newRpb,
TRIGGER_UPDATE, POST_TRIG);
@ -8871,7 +8871,7 @@ const StmtNode* StoreNode::store(thread_db* tdbb, Request* request, WhichTrigger
{
SavepointChangeMarker scMarker(transaction);
if (relation && relation->rel_pre_store && whichTrig != POST_TRIG)
if (relation && (relation->rel_pre_store || relation->isSystem()) && whichTrig != POST_TRIG)
{
EXE_execute_triggers(tdbb, &relation->rel_pre_store, NULL, rpb,
TRIGGER_INSERT, PRE_TRIG);
@ -8904,7 +8904,8 @@ const StmtNode* StoreNode::store(thread_db* tdbb, Request* request, WhichTrigger
rpb->rpb_number.setValid(true);
if (relation && relation->rel_post_store && whichTrig != PRE_TRIG)
if (relation && (relation->rel_post_store || relation->isSystem()) &&
relation->rel_post_store && whichTrig != PRE_TRIG)
{
EXE_execute_triggers(tdbb, &relation->rel_post_store, NULL, rpb,
TRIGGER_INSERT, POST_TRIG);
@ -11548,13 +11549,10 @@ static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jr
bool userTriggers = false;
for (FB_SIZE_T i = 0; i < trigger->getCount(); i++)
{
if (!(*trigger)[i].sysTrigger)
{
userTriggers = true;
break;
}
}
if (userTriggers)
{
@ -11660,9 +11658,10 @@ static void preModifyEraseTriggers(thread_db* tdbb, TrigVector** trigs,
FB_NEW_POOL(*tdbb->getTransaction()->tra_pool) traRpbList(*tdbb->getTransaction()->tra_pool);
}
const auto relation = rpb->rpb_relation;
const int rpblevel = tdbb->getTransaction()->tra_rpblist->PushRpb(rpb);
if (*trigs && whichTrig != StmtNode::POST_TRIG)
if ((*trigs || relation->isSystem()) && whichTrig != StmtNode::POST_TRIG)
{
try
{

View File

@ -1498,8 +1498,7 @@ void Monitoring::dumpAttachment(thread_db* tdbb, Attachment* attachment, ULONG g
{
request->adjustCallerStats();
if (!(request->getStatement()->flags &
(Statement::FLAG_INTERNAL | Statement::FLAG_SYS_TRIGGER)) &&
if (!(request->getStatement()->flags & Statement::FLAG_INTERNAL) &&
request->req_caller)
{
putCall(record, request);
@ -1513,7 +1512,7 @@ void Monitoring::dumpAttachment(thread_db* tdbb, Attachment* attachment, ULONG g
for (const auto statement : attachment->att_statements)
{
if (!(statement->flags & (Statement::FLAG_INTERNAL | Statement::FLAG_SYS_TRIGGER)))
if (!(statement->flags & Statement::FLAG_INTERNAL))
{
const string plan = Optimizer::getPlan(tdbb, statement, true);
putStatement(record, statement, plan);
@ -1527,7 +1526,7 @@ void Monitoring::dumpAttachment(thread_db* tdbb, Attachment* attachment, ULONG g
{
const auto statement = request->getStatement();
if (!(statement->flags & (Statement::FLAG_INTERNAL | Statement::FLAG_SYS_TRIGGER)))
if (!(statement->flags & Statement::FLAG_INTERNAL))
{
const string plan = Optimizer::getPlan(tdbb, statement, true);
putRequest(record, request, plan);

View File

@ -626,8 +626,6 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
{
MET_scan_relation(tdbb, node->relation);
}
else if (node->relation->rel_flags & REL_sys_triggers)
MET_parse_sys_trigger(tdbb, node->relation);
// generate a stream for the relation reference, assuming it is a real reference

View File

@ -393,11 +393,9 @@ const ULONG REL_deleted = 0x0004; // Relation known gonzo
const ULONG REL_get_dependencies = 0x0008; // New relation needs dependencies during scan
const ULONG REL_check_existence = 0x0010; // Existence lock released pending drop of relation
const ULONG REL_blocking = 0x0020; // Blocking someone from dropping relation
const ULONG REL_sys_triggers = 0x0040; // The relation has system triggers to compile
const ULONG REL_sql_relation = 0x0080; // Relation defined as sql table
const ULONG REL_check_partners = 0x0100; // Rescan primary dependencies and foreign references
const ULONG REL_being_scanned = 0x0200; // relation scan in progress
const ULONG REL_sys_trigs_being_loaded = 0x0400; // System triggers being loaded
const ULONG REL_deleting = 0x0800; // relation delete in progress
const ULONG REL_temp_tran = 0x1000; // relation is a GTT delete rows
const ULONG REL_temp_conn = 0x2000; // relation is a GTT preserve rows

View File

@ -34,11 +34,10 @@ class PlanEntry;
class Statement : public pool_alloc<type_req>
{
public:
static const unsigned FLAG_SYS_TRIGGER = 0x01;
static const unsigned FLAG_INTERNAL = 0x02;
static const unsigned FLAG_IGNORE_PERM = 0x04;
//static const unsigned FLAG_VERSION4 = 0x08;
static const unsigned FLAG_POWERFUL = FLAG_SYS_TRIGGER | FLAG_INTERNAL | FLAG_IGNORE_PERM;
static const unsigned FLAG_POWERFUL = FLAG_INTERNAL | FLAG_IGNORE_PERM;
//static const unsigned MAP_LENGTH; // CVC: Moved to dsql/Nodes.h as STREAM_MAP_LENGTH
static const unsigned MAX_CLONES = 1000;

1275
src/jrd/SystemTriggers.epp Normal file

File diff suppressed because it is too large Load Diff

57
src/jrd/SystemTriggers.h Normal file
View File

@ -0,0 +1,57 @@
/*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2024 Adriano dos Santos Fernandes <adrianosf@gmail.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#ifndef JRD_SYSTEM_TRIGGERS_H
#define JRD_SYSTEM_TRIGGERS_H
#include "firebird.h"
namespace Jrd
{
class thread_db;
class Record;
} // namespace Jrd
namespace Jrd::SystemTriggers
{
void beforeDeleteCheckConstraint(thread_db* tdbb, Record* record);
void afterDeleteCheckConstraint(thread_db* tdbb, Record* record);
void beforeUpdateCheckConstraint(thread_db* tdbb, Record* orgRecord, Record* newRecord);
void beforeDeleteIndex(thread_db* tdbb, Record* record);
void beforeUpdateIndex(thread_db* tdbb, Record* orgRecord, Record* newRecord);
void beforeDeleteIndexSegment(thread_db* tdbb, Record* record);
void beforeUpdateIndexSegment(thread_db* tdbb, Record* orgRecord, Record* newRecord);
void beforeUpdateField(thread_db* tdbb, Record* orgRecord, Record* newRecord);
void beforeInsertRefConstraint(thread_db* tdbb, Record* record);
void beforeDeleteRelationConstraint(thread_db* tdbb, Record* record);
void afterDeleteRelationConstraint(thread_db* tdbb, Record* record);
void beforeInsertRelationConstraint(thread_db* tdbb, Record* record);
void beforeDeleteRelationField(thread_db* tdbb, Record* record);
void afterDeleteRelationField(thread_db* tdbb, Record* record);
void beforeUpdateRelationField(thread_db* tdbb, Record* orgRecord, Record* newRecord);
void beforeDeleteTrigger(thread_db* tdbb, Record* record);
void beforeUpdateTrigger(thread_db* tdbb, Record* orgRecord, Record* newRecord);
void beforeDeleteUserPrivilege(thread_db* tdbb, Record* record);
void beforeInsertUserPrivilege(thread_db* tdbb, Record* record);
} // namespace Jrd::SystemTriggers
#endif // JRD_SYSTEM_TRIGGERS_H

View File

@ -6304,8 +6304,6 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
// We have just loaded the triggers onto the local vector triggers.
// It's now time to place them at their rightful place inside the relation block.
if (!(relation->rel_flags & REL_sys_trigs_being_loaded))
relation->replaceTriggers(tdbb, triggers);
// in case somebody changed the view definition or a computed

View File

@ -71,6 +71,7 @@
#include "../jrd/intl.h"
#include "../jrd/sbm.h"
#include "../jrd/blb.h"
#include "../jrd/SystemTriggers.h"
#include "firebird/impl/blr.h"
#include "../dsql/ExprNodes.h"
#include "../dsql/StmtNodes.h"
@ -1294,18 +1295,123 @@ void EXE_execute_triggers(thread_db* tdbb,
* if any blow up.
*
**************************************/
SET_TDBB(tdbb);
const auto dbb = tdbb->getDatabase();
const auto old_rec = old_rpb ? old_rpb->rpb_record : nullptr;
const auto new_rec = new_rpb ? new_rpb->rpb_record : nullptr;
if (!(dbb->dbb_flags & DBB_creating) && (old_rpb || new_rpb))
{
if (const auto relation = old_rpb ? old_rpb->rpb_relation : new_rpb->rpb_relation;
relation->rel_flags & REL_system)
{
if (which_trig == StmtNode::PRE_TRIG && trigger_action == TriggerAction::TRIGGER_DELETE)
{
switch ((RIDS) relation->rel_id)
{
case rel_ccon:
SystemTriggers::beforeDeleteCheckConstraint(tdbb, old_rec);
break;
case rel_indices:
SystemTriggers::beforeDeleteIndex(tdbb, old_rec);
break;
case rel_priv:
SystemTriggers::beforeDeleteUserPrivilege(tdbb, old_rec);
break;
case rel_rcon:
SystemTriggers::beforeDeleteRelationConstraint(tdbb, old_rec);
break;
case rel_rfr:
SystemTriggers::beforeDeleteRelationField(tdbb, old_rec);
break;
case rel_segments:
SystemTriggers::beforeDeleteIndexSegment(tdbb, old_rec);
break;
case rel_triggers:
SystemTriggers::beforeDeleteTrigger(tdbb, old_rec);
break;
}
}
else if (which_trig == StmtNode::PRE_TRIG && trigger_action == TriggerAction::TRIGGER_UPDATE)
{
switch ((RIDS) relation->rel_id)
{
case rel_ccon:
SystemTriggers::beforeUpdateCheckConstraint(tdbb, old_rec, new_rec);
break;
case rel_fields:
SystemTriggers::beforeUpdateField(tdbb, old_rec, new_rec);
break;
case rel_indices:
SystemTriggers::beforeUpdateIndex(tdbb, old_rec, new_rec);
break;
case rel_rfr:
SystemTriggers::beforeUpdateRelationField(tdbb, old_rec, new_rec);
break;
case rel_segments:
SystemTriggers::beforeUpdateIndexSegment(tdbb, old_rec, new_rec);
break;
case rel_triggers:
SystemTriggers::beforeUpdateTrigger(tdbb, old_rec, new_rec);
break;
}
}
else if (which_trig == StmtNode::PRE_TRIG && trigger_action == TriggerAction::TRIGGER_INSERT)
{
switch ((RIDS) relation->rel_id)
{
case rel_priv:
SystemTriggers::beforeInsertUserPrivilege(tdbb, new_rec);
break;
case rel_rcon:
SystemTriggers::beforeInsertRelationConstraint(tdbb, new_rec);
break;
case rel_refc:
SystemTriggers::beforeInsertRefConstraint(tdbb, new_rec);
break;
}
}
else if (which_trig == StmtNode::POST_TRIG && trigger_action == TriggerAction::TRIGGER_DELETE)
{
switch ((RIDS) relation->rel_id)
{
case rel_ccon:
SystemTriggers::afterDeleteCheckConstraint(tdbb, old_rec);
break;
case rel_rcon:
SystemTriggers::afterDeleteRelationConstraint(tdbb, old_rec);
break;
case rel_rfr:
SystemTriggers::afterDeleteRelationField(tdbb, old_rec);
break;
}
}
}
}
if (!*triggers || (*triggers)->isEmpty())
return;
SET_TDBB(tdbb);
Request* const request = tdbb->getRequest();
jrd_tra* const transaction = request ? request->req_transaction : tdbb->getTransaction();
RefPtr<TrigVector> vector(*triggers);
Record* const old_rec = old_rpb ? old_rpb->rpb_record : NULL;
Record* const new_rec = new_rpb ? new_rpb->rpb_record : NULL;
AutoPtr<Record> null_rec;
const bool is_db_trigger = (!old_rec && !new_rec);
@ -1868,15 +1974,6 @@ static void trigger_failure(thread_db* tdbb, Request* trigger)
MET_trigger_msg(tdbb, msg, trigger->getStatement()->triggerName, trigger->req_label);
if (msg.hasData())
{
if (trigger->getStatement()->flags & Statement::FLAG_SYS_TRIGGER)
{
ISC_STATUS code = PAR_symbol_to_gdscode(msg);
if (code)
{
ERR_post(Arg::Gds(isc_integ_fail) << Arg::Num(trigger->req_label) <<
Arg::Gds(code));
}
}
ERR_post(Arg::Gds(isc_integ_fail) << Arg::Num(trigger->req_label) <<
Arg::Gds(isc_random) << Arg::Str(msg));
}

View File

@ -79,134 +79,6 @@ namespace
jrd_vtof(name.c_str(), field, sizeof(field));
}
// This is the table used in defining triggers; note that
// RDB$TRIGGER_0 was first changed to RDB$TRIGGER_7 to make it easier to
// upgrade a database to support field-level grant. It has since been
// changed to RDB$TRIGGER_9 to handle SQL security on relations whose
// name is > 27 characters
const jrd_trg triggers[] =
{
{ "RDB$TRIGGER_1", (UCHAR) nam_user_privileges,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_USER_PRIVILEGES_TRIGGER_1_BEFORE_UPDATE),
TRIGGER_BLR_RDB_USER_PRIVILEGES_TRIGGER_1_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_8", (UCHAR) nam_user_privileges,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(TRIGGER_BLR_RDB_USER_PRIVILEGES_TRIGGER_8_BEFORE_DELETE),
TRIGGER_BLR_RDB_USER_PRIVILEGES_TRIGGER_8_BEFORE_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_9", (UCHAR) nam_user_privileges,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(TRIGGER_BLR_RDB_USER_PRIVILEGES_TRIGGER_9_BEFORE_INSERT),
TRIGGER_BLR_RDB_USER_PRIVILEGES_TRIGGER_9_BEFORE_INSERT, 0, ODS_8_0 },
{ "RDB$TRIGGER_2", (UCHAR) nam_trgs,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_TRIGGERS_TRIGGER_2_BEFORE_UPDATE),
TRIGGER_BLR_RDB_TRIGGERS_TRIGGER_2_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_3", (UCHAR) nam_trgs,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(TRIGGER_BLR_RDB_TRIGGERS_TRIGGER_3_BEFORE_DELETE),
TRIGGER_BLR_RDB_TRIGGERS_TRIGGER_3_BEFORE_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_26", (UCHAR) nam_rel_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_26_BEFORE_INSERT),
TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_26_BEFORE_INSERT, 0, ODS_8_0 },
{ "RDB$TRIGGER_25", (UCHAR) nam_rel_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_25_BEFORE_UPDATE),
TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_25_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_10", (UCHAR) nam_rel_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_10_BEFORE_DELETE),
TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_10_BEFORE_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_11", (UCHAR) nam_rel_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_11_AFTER_DELETE),
TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_11_AFTER_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_12", (UCHAR) nam_ref_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(TRIGGER_BLR_RDB_REF_CONSTRAINTS_TRIGGER_12_BEFORE_INSERT),
TRIGGER_BLR_RDB_REF_CONSTRAINTS_TRIGGER_12_BEFORE_INSERT, 0, ODS_8_0 },
{ "RDB$TRIGGER_13", (UCHAR) nam_ref_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_REF_CONSTRAINTS_TRIGGER_13_BEFORE_UPDATE),
TRIGGER_BLR_RDB_REF_CONSTRAINTS_TRIGGER_13_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_14", (UCHAR) nam_chk_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_CHECK_CONSTRAINTS_TRIGGER_14_BEFORE_UPDATE),
TRIGGER_BLR_RDB_CHECK_CONSTRAINTS_TRIGGER_14_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_15", (UCHAR) nam_chk_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(TRIGGER_BLR_RDB_CHECK_CONSTRAINTS_TRIGGER_15_BEFORE_DELETE),
TRIGGER_BLR_RDB_CHECK_CONSTRAINTS_TRIGGER_15_BEFORE_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_16", (UCHAR) nam_chk_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(TRIGGER_BLR_RDB_CHECK_CONSTRAINTS_TRIGGER_16_AFTER_DELETE),
TRIGGER_BLR_RDB_CHECK_CONSTRAINTS_TRIGGER_16_AFTER_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_17", (UCHAR) nam_i_segments,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(TRIGGER_BLR_RDB_INDEX_SEGMENTS_TRIGGER_17_BEFORE_DELETE),
TRIGGER_BLR_RDB_INDEX_SEGMENTS_TRIGGER_17_BEFORE_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_18", (UCHAR) nam_i_segments,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_INDEX_SEGMENTS_TRIGGER_18_BEFORE_UPDATE),
TRIGGER_BLR_RDB_INDEX_SEGMENTS_TRIGGER_18_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_19", (UCHAR) nam_indices,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(TRIGGER_BLR_RDB_INDICES_TRIGGER_19_BEFORE_DELETE),
TRIGGER_BLR_RDB_INDICES_TRIGGER_19_BEFORE_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_20", (UCHAR) nam_indices,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_INDICES_TRIGGER_20_BEFORE_UPDATE),
TRIGGER_BLR_RDB_INDICES_TRIGGER_20_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_21", (UCHAR) nam_trgs,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(TRIGGER_BLR_RDB_TRIGGERS_TRIGGER_21_BEFORE_DELETE),
TRIGGER_BLR_RDB_TRIGGERS_TRIGGER_21_BEFORE_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_22", (UCHAR) nam_trgs,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_TRIGGERS_TRIGGER_22_BEFORE_UPDATE),
TRIGGER_BLR_RDB_TRIGGERS_TRIGGER_22_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_23", (UCHAR) nam_r_fields,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(TRIGGER_BLR_RDB_RELATION_FIELDS_TRIGGER_23_BEFORE_DELETE),
TRIGGER_BLR_RDB_RELATION_FIELDS_TRIGGER_23_BEFORE_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_24", (UCHAR) nam_r_fields,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_RELATION_FIELDS_TRIGGER_24_BEFORE_UPDATE),
TRIGGER_BLR_RDB_RELATION_FIELDS_TRIGGER_24_BEFORE_UPDATE, 0, ODS_8_0 },
{ "RDB$TRIGGER_27", (UCHAR) nam_r_fields,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(TRIGGER_BLR_RDB_RELATION_FIELDS_TRIGGER_27_AFTER_DELETE),
TRIGGER_BLR_RDB_RELATION_FIELDS_TRIGGER_27_AFTER_DELETE, 0, ODS_8_0 },
{ "RDB$TRIGGER_34", (UCHAR) nam_rel_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_34_AFTER_DELETE),
TRIGGER_BLR_RDB_RELATION_CONSTRAINTS_TRIGGER_34_AFTER_DELETE, TRG_ignore_perm, ODS_8_1 },
{ "RDB$TRIGGER_35", (UCHAR) nam_chk_constr,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(TRIGGER_BLR_RDB_CHECK_CONSTRAINTS_TRIGGER_35_AFTER_DELETE),
TRIGGER_BLR_RDB_CHECK_CONSTRAINTS_TRIGGER_35_AFTER_DELETE, TRG_ignore_perm, ODS_8_1 },
{ "RDB$TRIGGER_36", (UCHAR) nam_fields,
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(TRIGGER_BLR_RDB_FIELDS_TRIGGER_36_BEFORE_UPDATE),
TRIGGER_BLR_RDB_FIELDS_TRIGGER_36_BEFORE_UPDATE, 0, ODS_11_0 },
{ 0, 0, 0, 0, 0, 0 }
};
// this table is used in defining messages for system triggers
const trigger_msg trigger_messages[] =
{
{ "RDB$TRIGGER_9", 0, "grant_obj_notfound", ODS_8_0 },
{ "RDB$TRIGGER_9", 1, "grant_fld_notfound", ODS_8_0 },
{ "RDB$TRIGGER_9", 2, "grant_nopriv", ODS_8_0 },
{ "RDB$TRIGGER_9", 3, "nonsql_security_rel", ODS_8_0 },
{ "RDB$TRIGGER_9", 4, "nonsql_security_fld", ODS_8_0 },
{ "RDB$TRIGGER_9", 5, "grant_nopriv_on_base", ODS_8_0 },
{ "RDB$TRIGGER_1", 0, "existing_priv_mod", ODS_8_0 },
{ "RDB$TRIGGER_2", 0, "systrig_update", ODS_8_0 },
{ "RDB$TRIGGER_3", 0, "systrig_update", ODS_8_0 },
{ "RDB$TRIGGER_24", 1, "cnstrnt_fld_rename", ODS_8_0 },
{ "RDB$TRIGGER_23", 1, "cnstrnt_fld_del", ODS_8_0 },
{ "RDB$TRIGGER_22", 1, "check_trig_update", ODS_8_0 },
{ "RDB$TRIGGER_21", 1, "check_trig_del", ODS_8_0 },
{ "RDB$TRIGGER_20", 1, "integ_index_mod", ODS_8_0 },
{ "RDB$TRIGGER_20", 2, "integ_index_deactivate", ODS_8_0 },
{ "RDB$TRIGGER_20", 3, "integ_deactivate_primary", ODS_8_0 },
{ "RDB$TRIGGER_19", 1, "integ_index_del", ODS_8_0 },
{ "RDB$TRIGGER_18", 1, "integ_index_seg_mod", ODS_8_0 },
{ "RDB$TRIGGER_17", 1, "integ_index_seg_del", ODS_8_0 },
{ "RDB$TRIGGER_15", 1, "check_cnstrnt_del", ODS_8_0 },
{ "RDB$TRIGGER_14", 1, "check_cnstrnt_update", ODS_8_0 },
{ "RDB$TRIGGER_13", 1, "ref_cnstrnt_update", ODS_8_0 },
{ "RDB$TRIGGER_12", 1, "ref_cnstrnt_notfound", ODS_8_0 },
{ "RDB$TRIGGER_12", 2, "foreign_key_notfound", ODS_8_0 },
{ "RDB$TRIGGER_10", 1, "primary_key_ref", ODS_8_0 },
{ "RDB$TRIGGER_10", 2, "primary_key_notnull", ODS_8_0 },
{ "RDB$TRIGGER_25", 1, "rel_cnstrnt_update", ODS_8_0 },
{ "RDB$TRIGGER_26", 1, "constaint_on_view", ODS_8_0 },
{ "RDB$TRIGGER_26", 2, "invld_cnstrnt_type", ODS_8_0 },
{ "RDB$TRIGGER_26", 3, "primary_key_exists", ODS_8_0 },
{ "RDB$TRIGGER_24", 2, "integ_index_seg_mod", ODS_11_0 },
{ "RDB$TRIGGER_36", 1, "integ_index_seg_mod", ODS_11_0 },
{ 0, 0, 0, 0 }
};
unsigned getLatestFormat(thread_db* tdbb, int relId, int maxFieldId)
{
const auto relation = MET_relation(tdbb, relId);
@ -730,11 +602,9 @@ static void store_generator(thread_db*, const gen*, AutoRequest&, NonRelationSec
static void store_global_field(thread_db*, const gfld*, AutoRequest&, NonRelationSecurity&);
static void store_indices(thread_db*, USHORT = 0);
static void store_intlnames(thread_db*, NonRelationSecurity&);
static void store_message(thread_db*, const trigger_msg*, AutoRequest&);
static void store_relation(thread_db*, int, const char*, int, int, AutoRequest&, RelationSecurity&);
static void store_relation_field(thread_db*, int, const char*, const char*, const char*, int, AutoRequest&);
static void store_packages(thread_db*, NonRelationSecurity&, USHORT = 0);
static void store_trigger(thread_db*, const jrd_trg*, AutoRequest&);
//
@ -779,6 +649,8 @@ void INI_format(thread_db* tdbb, const string& charset)
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
{
const bool isVirtual = (relfld[RFLD_R_TYPE] == rel_virtual);
bool needsRdbRuntime = false;
int fieldId = 0;
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME]; fld += RFLD_F_LENGTH)
@ -790,6 +662,9 @@ void INI_format(thread_db* tdbb, const string& charset)
const auto globalName = names[gfield->gfld_name];
const auto updateFlag = fld[RFLD_F_UPDATE];
if (!isVirtual && (gfield->gfld_dflt_blr || !gfield->gfld_nullable))
needsRdbRuntime = true;
store_relation_field(tdbb, fieldId, relName, fieldName, globalName,
updateFlag, handle2);
++fieldId;
@ -800,6 +675,13 @@ void INI_format(thread_db* tdbb, const string& charset)
const auto relType = relfld[RFLD_R_TYPE];
store_relation(tdbb, relId, relName, fieldId, relType, handle, relSec);
if (needsRdbRuntime)
{
dsc desc;
desc.makeText(static_cast<USHORT>(strlen(relName)), CS_METADATA, (UCHAR*) relName);
DFW_post_work(transaction, dfw_update_format, &desc, 0);
}
}
}
@ -896,20 +778,6 @@ void INI_format(thread_db* tdbb, const string& charset)
// Adjust the value of the hidden generator RDB$GENERATORS
DPM_gen_id(tdbb, 0, true, FB_NELEM(generators) - 1);
// Store system-defined triggers
handle.reset();
for (const jrd_trg* trigger = triggers; trigger->trg_relation; ++trigger)
store_trigger(tdbb, trigger, handle);
// Store trigger messages to go with triggers
handle.reset();
for (const trigger_msg* message = trigger_messages; message->trigmsg_name; ++message)
store_message(tdbb, message, handle);
// Create system packages
// Reset nonRelSec for package permissions, it should be its last usage in this function
@ -952,22 +820,6 @@ void INI_format(thread_db* tdbb, const string& charset)
}
//
// Return the trigger flags for a system trigger
//
USHORT INI_get_trig_flags(const MetaName& triggerName)
{
for (const jrd_trg* trig = triggers; trig->trg_length > 0; trig++)
{
if (triggerName == trig->trg_name)
return trig->trg_flags;
}
return 0;
}
//
// Initialize in-memory meta data
//
@ -989,17 +841,6 @@ void INI_init(thread_db* tdbb)
relation->rel_flags |= MET_get_rel_flags_from_TYPE(relfld[RFLD_R_TYPE]);
relation->rel_name = names[relfld[RFLD_R_NAME]];
// Set a flag if their is a trigger on the relation. Later we may need to compile it.
for (const jrd_trg* trigger = triggers; trigger->trg_relation; trigger++)
{
if (relation->rel_name == names[trigger->trg_relation])
{
relation->rel_flags |= REL_sys_triggers;
break;
}
}
HalfStaticArray<const char*, 64> fieldNames;
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME]; fld += RFLD_F_LENGTH)
{
@ -1102,6 +943,30 @@ void INI_init(thread_db* tdbb)
}
// Rescan system relations that have fields with default values.
void INI_init_sys_relations(thread_db* tdbb)
{
const int* fld;
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
{
jrd_rel* relation = MET_relation(tdbb, relfld[RFLD_R_ID]);
bool needsRdbRuntime = false;
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME]; fld += RFLD_F_LENGTH)
{
const auto* const gfield = &gfields[fld[RFLD_F_ID]];
if (!relation->isVirtual() && (gfield->gfld_dflt_blr || !gfield->gfld_nullable))
needsRdbRuntime = true;
}
if (needsRdbRuntime)
MET_scan_relation(tdbb, relation);
}
}
//
// Load system objects into DSQL metadata cache
//
@ -1373,26 +1238,6 @@ void INI_upgrade(thread_db* tdbb)
context = "indices";
store_indices(tdbb, odsVersion);
// Create new system triggers and their trigger messages
context = "triggers";
handle.reset();
for (const jrd_trg* trigger = triggers; trigger->trg_relation; ++trigger)
{
if (trigger->trg_ods_version > odsVersion)
store_trigger(tdbb, trigger, handle);
}
context = "trigger messages";
handle.reset();
for (const trigger_msg* message = trigger_messages; message->trigmsg_name; ++message)
{
if (message->trg_ods_version > odsVersion)
store_message(tdbb, message, handle);
}
// Create new system generators
context = "generators";
@ -1944,22 +1789,6 @@ static void store_intlnames(thread_db* tdbb, NonRelationSecurity& security)
}
static void store_message(thread_db* tdbb, const trigger_msg* message, AutoRequest& handle)
{
const auto attachment = tdbb->getAttachment();
const auto transaction = tdbb->getTransaction();
STORE(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
X IN RDB$TRIGGER_MESSAGES
{
PAD(message->trigmsg_name, X.RDB$TRIGGER_NAME);
X.RDB$MESSAGE_NUMBER = message->trigmsg_number;
PAD(message->trigmsg_text, X.RDB$MESSAGE);
}
END_STORE
}
static void store_relation(thread_db* tdbb,
int relId,
const char* relName,
@ -2226,36 +2055,3 @@ static void store_packages(thread_db* tdbb, NonRelationSecurity& security, USHOR
}
}
}
static void store_trigger(thread_db* tdbb, const jrd_trg* trigger, AutoRequest& handle)
{
const auto attachment = tdbb->getAttachment();
const auto transaction = tdbb->getTransaction();
// Indicate that the relation format needs revising
const auto triggerName = names[trigger->trg_relation];
dsc desc;
desc.makeText(static_cast<USHORT>(strlen(triggerName)), CS_METADATA,
(UCHAR*) triggerName);
DFW_post_work(transaction, dfw_update_format, &desc, 0);
// Store the trigger
STORE(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
X IN RDB$TRIGGERS
{
PAD(trigger->trg_name, X.RDB$TRIGGER_NAME);
PAD(names[trigger->trg_relation], X.RDB$RELATION_NAME);
X.RDB$TRIGGER_SEQUENCE = 0;
X.RDB$SYSTEM_FLAG = RDB_system;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
X.RDB$TRIGGER_TYPE = trigger->trg_type;
X.RDB$FLAGS = trigger->trg_flags;
attachment->storeBinaryBlob(tdbb, transaction, &X.RDB$TRIGGER_BLR,
ByteChunk(trigger->trg_blr, trigger->trg_length));
}
END_STORE
}

View File

@ -30,8 +30,8 @@ namespace Jrd {
}
void INI_format(Jrd::thread_db*, const Firebird::string&);
USHORT INI_get_trig_flags(const Jrd::MetaName&);
void INI_init(Jrd::thread_db*);
void INI_init_sys_relations(Jrd::thread_db*);
void INI_init_dsql(Jrd::thread_db*, Jrd::dsql_dbb* database);
Firebird::string INI_owner_privileges();
void INI_upgrade(Jrd::thread_db*);

View File

@ -54,7 +54,6 @@ enum irq_type_t
irq_l_funct_blr, // lookup function BLR and debug info
irq_l_args, // lookup function arguments
irq_s_triggers, // scan triggers
irq_s_triggers2, // scan triggers
irq_s_msgs, // search for message
irq_grant1, // process grant option
irq_grant2, // process grant option

View File

@ -944,9 +944,6 @@ void Trigger::compile(thread_db* tdbb)
if (ssDefiner.asBool())
statement->triggerInvoker = att->getUserId(owner);
if (sysTrigger)
statement->flags |= Statement::FLAG_SYS_TRIGGER | Statement::FLAG_INTERNAL;
if (flags & TRG_ignore_perm)
statement->flags |= Statement::FLAG_IGNORE_PERM;
}
@ -955,15 +952,7 @@ void Trigger::release(thread_db* tdbb)
{
extTrigger.reset();
// dimitr: We should never release triggers created by MET_parse_sys_trigger().
// System triggers do have BLR, but it's not stored inside the trigger object.
// However, triggers backing RI constraints are also marked as system,
// but they are loaded in a regular way and their BLR is present here.
// This is why we cannot simply check for sysTrigger, sigh.
const bool sysTableTrigger = (blr.isEmpty() && engine.isEmpty());
if (sysTableTrigger || !statement || statement->isActive() || releaseInProgress)
if (!statement || statement->isActive() || releaseInProgress)
return;
AutoSetRestore<bool> autoProgressFlag(&releaseInProgress, true);
@ -1904,6 +1893,8 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
PAG_attachment_id(tdbb);
INI_init_sys_relations(tdbb);
bool cleanupTransactions = false;
if (!options.dpb_verify && CCH_exclusive(tdbb, LCK_PW, LCK_NO_WAIT, NULL))
@ -9230,11 +9221,7 @@ ISC_STATUS thread_db::getCancelState(ISC_STATUS* secondary)
if ((attachment->att_flags & ATT_cancel_raise) &&
!(attachment->att_flags & ATT_cancel_disable))
{
if ((!request ||
!(request->getStatement()->flags &
// temporary change to fix shutdown
(/*Statement::FLAG_INTERNAL | */Statement::FLAG_SYS_TRIGGER))) &&
(!transaction || !(transaction->tra_flags & TRA_system)))
if ((!transaction || !(transaction->tra_flags & TRA_system)))
{
return isc_cancelled;
}

View File

@ -142,7 +142,6 @@ public:
Firebird::HalfStaticArray<UCHAR, 128> debugInfo; // Debug info
Statement* statement = nullptr; // Compiled statement
bool releaseInProgress = false;
bool sysTrigger = false;
FB_UINT64 type = 0; // Trigger type
USHORT flags = 0; // Flags as they are in RDB$TRIGGERS table
jrd_rel* relation = nullptr; // Trigger parent relation

View File

@ -115,7 +115,7 @@ static int blocking_ast_relation(void*);
static int partners_ast_relation(void*);
static int rescan_ast_relation(void*);
static ULONG get_rel_flags_from_FLAGS(USHORT);
static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, TrigVector**, const TEXT*, FB_UINT64, bool,
static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, TrigVector**, const TEXT*, FB_UINT64,
USHORT, const MetaName&, const string&, const bid*, TriState ssDefiner);
static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*);
static void lookup_view_contexts(thread_db*, jrd_rel*);
@ -124,7 +124,7 @@ static ValueExprNode* parse_field_default_blr(thread_db* tdbb, bid* blob_id);
static BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, const MetaName name);
static bool resolve_charset_and_collation(thread_db*, USHORT*, const UCHAR*, const UCHAR*);
static void save_trigger_data(thread_db*, TrigVector**, jrd_rel*, Statement*, blb*, blb*,
const TEXT*, FB_UINT64, bool, USHORT, const MetaName&, const string&,
const TEXT*, FB_UINT64, USHORT, const MetaName&, const string&,
const bid*, TriState ssDefiner);
static void scan_partners(thread_db*, jrd_rel*);
static bool verify_TRG_ignore_perm(thread_db*, const MetaName&);
@ -1928,9 +1928,6 @@ void MET_load_trigger(thread_db* tdbb,
if (relation)
{
if (relation->rel_flags & REL_sys_trigs_being_loaded)
return;
// No need to load table triggers for ReadOnly databases,
// since INSERT/DELETE/UPDATE statements are not going to be allowed
// hvlad: GTT with ON COMMIT DELETE ROWS clause is writable
@ -2006,7 +2003,6 @@ void MET_load_trigger(thread_db* tdbb,
triggers,
TRG.RDB$TRIGGER_NAME,
TRG.RDB$TRIGGER_TYPE,
(bool) TRG.RDB$SYSTEM_FLAG,
trig_flags,
engine,
entryPoint,
@ -2027,7 +2023,6 @@ void MET_load_trigger(thread_db* tdbb,
triggers + trigger_action,
TRG.RDB$TRIGGER_NAME,
(UCHAR) trigger_action,
(bool) TRG.RDB$SYSTEM_FLAG,
trig_flags,
engine,
entryPoint,
@ -3213,111 +3208,6 @@ DmlNode* MET_parse_blob(thread_db* tdbb,
}
void MET_parse_sys_trigger(thread_db* tdbb, jrd_rel* relation)
{
/**************************************
*
* M E T _ p a r s e _ s y s _ t r i g g e r
*
**************************************
*
* Functional description
* Parse the blr for a system relation's triggers.
*
**************************************/
SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment();
Database* dbb = tdbb->getDatabase();
relation->rel_flags &= ~REL_sys_triggers;
// Release any triggers in case of a rescan
relation->releaseTriggers(tdbb, true);
// No need to load triggers for ReadOnly databases, since
// INSERT/DELETE/UPDATE statements are not going to be allowed
// hvlad: GTT with ON COMMIT DELETE ROWS clause is writable
if (dbb->readOnly() && !(relation->rel_flags & REL_temp_tran))
return;
relation->rel_flags |= REL_sys_trigs_being_loaded;
AutoCacheRequest request(tdbb, irq_s_triggers2, IRQ_REQUESTS);
FOR (REQUEST_HANDLE request)
TRG IN RDB$TRIGGERS
WITH TRG.RDB$RELATION_NAME = relation->rel_name.c_str()
AND TRG.RDB$SYSTEM_FLAG = 1
{
const FB_UINT64 type = TRG.RDB$TRIGGER_TYPE;
const USHORT trig_flags = TRG.RDB$FLAGS;
const TEXT* name = TRG.RDB$TRIGGER_NAME;
TrigVector** ptr;
switch (type)
{
case TRIGGER_PRE_STORE:
ptr = &relation->rel_pre_store;
break;
case TRIGGER_POST_STORE:
ptr = &relation->rel_post_store;
break;
case TRIGGER_PRE_MODIFY:
ptr = &relation->rel_pre_modify;
break;
case TRIGGER_POST_MODIFY:
ptr = &relation->rel_post_modify;
break;
case TRIGGER_PRE_ERASE:
ptr = &relation->rel_pre_erase;
break;
case TRIGGER_POST_ERASE:
ptr = &relation->rel_post_erase;
break;
default:
ptr = NULL;
break;
}
if (ptr)
{
blb* blob = blb::open(tdbb, attachment->getSysTransaction(), &TRG.RDB$TRIGGER_BLR);
ULONG length = blob->blb_length + 10;
HalfStaticArray<UCHAR, 128> blr;
length = blob->BLB_get_data(tdbb, blr.getBuffer(length), length);
USHORT par_flags = (USHORT) ((trig_flags & TRG_ignore_perm) ? csb_ignore_perm : 0);
if (type & 1)
par_flags |= csb_pre_trigger;
else
par_flags |= csb_post_trigger;
Statement* statement = NULL;
{
Jrd::ContextPoolHolder context(tdbb, attachment->createPool());
PAR_blr(tdbb, relation, blr.begin(), length, NULL, NULL, &statement, true, par_flags);
}
statement->triggerName = name;
statement->flags |= Statement::FLAG_SYS_TRIGGER | Statement::FLAG_INTERNAL;
if (trig_flags & TRG_ignore_perm)
statement->flags |= Statement::FLAG_IGNORE_PERM;
save_trigger_data(tdbb, ptr, relation, statement, NULL, NULL, NULL, type, true, 0, "",
"", NULL, TriState());
}
}
END_FOR
relation->rel_flags &= ~REL_sys_trigs_being_loaded;
}
void MET_post_existence(thread_db* tdbb, jrd_rel* relation)
{
/**************************************
@ -3968,7 +3858,6 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
Database* dbb = tdbb->getDatabase();
Jrd::ContextPoolHolder context(tdbb, attachment->att_pool);
bool dependencies = false;
bool sys_triggers = false;
blb* blob = NULL;
@ -3985,8 +3874,7 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
relation->rel_flags |= REL_being_scanned;
dependencies = (relation->rel_flags & REL_get_dependencies) ? true : false;
sys_triggers = (relation->rel_flags & REL_sys_triggers) ? true : false;
relation->rel_flags &= ~(REL_get_dependencies | REL_sys_triggers);
relation->rel_flags &= ~REL_get_dependencies;
for (USHORT itr = 0; itr < TRIGGER_MAX; ++itr)
triggers[itr] = NULL;
@ -4274,17 +4162,7 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
// We have just loaded the triggers onto the local vector triggers.
// It's now time to place them at their rightful place inside the relation block.
if (!(relation->rel_flags & REL_sys_trigs_being_loaded))
{
// if we are scanning a system relation during loading the system
// triggers, (during parsing its blr actually), we must not release the
// existing system triggers; because we have already set the
// relation->rel_flag to not have REL_sys_trig, so these
// system triggers will not get loaded again. This fixes bug 8149.
relation->replaceTriggers(tdbb, triggers);
}
LCK_lock(tdbb, relation->rel_rescan_lock, LCK_SR, LCK_WAIT);
relation->rel_flags &= ~REL_being_scanned;
@ -4298,9 +4176,6 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
if (dependencies) {
relation->rel_flags |= REL_get_dependencies;
}
if (sys_triggers) {
relation->rel_flags |= REL_sys_triggers;
}
if (blob)
blob->BLB_close(tdbb);
@ -4670,7 +4545,7 @@ ULONG MET_get_rel_flags_from_TYPE(USHORT type)
static void get_trigger(thread_db* tdbb, jrd_rel* relation,
bid* blob_id, bid* debug_blob_id, TrigVector** ptr,
const TEXT* name, FB_UINT64 type,
bool sys_trigger, USHORT flags,
USHORT flags,
const MetaName& engine, const string& entryPoint,
const bid* body, TriState ssDefiner)
{
@ -4700,7 +4575,7 @@ static void get_trigger(thread_db* tdbb, jrd_rel* relation,
debugInfoBlob = blb::open(tdbb, attachment->getSysTransaction(), debug_blob_id);
save_trigger_data(tdbb, ptr, relation, NULL, blrBlob, debugInfoBlob,
name, type, sys_trigger, flags, engine, entryPoint, body, ssDefiner);
name, type, flags, engine, entryPoint, body, ssDefiner);
}
@ -5052,7 +4927,7 @@ static bool resolve_charset_and_collation(thread_db* tdbb,
static void save_trigger_data(thread_db* tdbb, TrigVector** ptr, jrd_rel* relation,
Statement* statement, blb* blrBlob, blb* debugInfoBlob,
const TEXT* name, FB_UINT64 type,
bool sys_trigger, USHORT flags,
USHORT flags,
const MetaName& engine, const string& entryPoint,
const bid* body, TriState ssDefiner)
{
@ -5109,7 +4984,6 @@ static void save_trigger_data(thread_db* tdbb, TrigVector** ptr, jrd_rel* relati
t.type = type;
t.flags = flags;
t.sysTrigger = sys_trigger;
t.statement = statement;
t.relation = relation;
t.engine = engine;
@ -5305,18 +5179,7 @@ void MET_store_dependencies(thread_db* tdbb,
SET_TDBB(tdbb);
const Trigger* t = 0;
const bool checkTableScope =
(dependency_type == obj_computed) ||
(dependency_type == obj_trigger) && (dep_rel != 0) &&
(
(t = findTrigger(dep_rel->rel_pre_erase, object_name)) ||
(t = findTrigger(dep_rel->rel_pre_modify, object_name)) ||
(t = findTrigger(dep_rel->rel_pre_store, object_name)) ||
(t = findTrigger(dep_rel->rel_post_erase, object_name)) ||
(t = findTrigger(dep_rel->rel_post_modify, object_name)) ||
(t = findTrigger(dep_rel->rel_post_store, object_name))
) && t && (t->sysTrigger);
const bool checkTableScope = dependency_type == obj_computed;
while (dependencies.hasData())
{
@ -5538,11 +5401,6 @@ static bool verify_TRG_ignore_perm(thread_db* tdbb, const MetaName& trig_name)
SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment();
// See if this is a system trigger, with the flag set as TRG_ignore_perm
if (INI_get_trig_flags(trig_name) & TRG_ignore_perm)
return true;
// See if this is a RI trigger
AutoCacheRequest request(tdbb, irq_c_trg_perm, IRQ_REQUESTS);

View File

@ -118,7 +118,6 @@ Jrd::jrd_rel* MET_lookup_relation(Jrd::thread_db*, const Jrd::MetaName&);
Jrd::jrd_rel* MET_lookup_relation_id(Jrd::thread_db*, SLONG, bool);
Jrd::DmlNode* MET_parse_blob(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::bid*, Jrd::CompilerScratch**,
Jrd::Statement**, bool, bool);
void MET_parse_sys_trigger(Jrd::thread_db*, Jrd::jrd_rel*);
void MET_post_existence(Jrd::thread_db*, Jrd::jrd_rel*);
void MET_prepare(Jrd::thread_db*, Jrd::jrd_tra*, USHORT, const UCHAR*);
Jrd::jrd_prc* MET_procedure(Jrd::thread_db*, USHORT, bool, USHORT);

View File

@ -242,6 +242,15 @@ int MOV_get_string(Jrd::thread_db* tdbb, const dsc* desc, UCHAR** address, vary*
}
void MOV_get_string(Jrd::thread_db* tdbb, const dsc* desc, string& str)
{
VaryStr<MAX_SQL_IDENTIFIER_SIZE> temp;
const char* strPtr = NULL;
const auto len = MOV_make_string(tdbb, desc, ttype_metadata, &strPtr, &temp, MAX_SQL_IDENTIFIER_SIZE);
str.assign(strPtr, len);
}
GDS_DATE MOV_get_sql_date(const dsc* desc)
{
/**************************************

View File

@ -42,6 +42,7 @@ SQUAD MOV_get_quad(Jrd::thread_db*, const dsc*, SSHORT);
SINT64 MOV_get_int64(Jrd::thread_db*, const dsc*, SSHORT);
int MOV_get_string_ptr(Jrd::thread_db*, const dsc*, USHORT*, UCHAR**, vary*, USHORT);
int MOV_get_string(Jrd::thread_db*, const dsc*, UCHAR**, vary*, USHORT);
void MOV_get_string(Jrd::thread_db* tdbb, const dsc* desc, Firebird::string& str);
GDS_DATE MOV_get_sql_date(const dsc*);
GDS_TIME MOV_get_sql_time(const dsc*);
ISC_TIME_TZ MOV_get_sql_time_tz(const dsc*);

View File

@ -431,8 +431,7 @@ public:
const auto attachment = m_tdbb->getAttachment();
const auto trace_mgr = attachment->att_trace_manager;
m_need_trace = !trigger->sysTrigger &&
trace_mgr->needs(ITraceFactory::TRACE_EVENT_TRIGGER_COMPILE);
m_need_trace = trace_mgr->needs(ITraceFactory::TRACE_EVENT_TRIGGER_COMPILE);
if (!m_need_trace)
return;
@ -529,8 +528,7 @@ public:
const auto transaction = m_tdbb->getTransaction();
const auto trace_mgr = attachment->att_trace_manager;
m_need_trace = !(m_request->getStatement()->flags & Statement::FLAG_SYS_TRIGGER) &&
trace_mgr->needs(ITraceFactory::TRACE_EVENT_TRIGGER_EXECUTE);
m_need_trace = trace_mgr->needs(ITraceFactory::TRACE_EVENT_TRIGGER_EXECUTE);
if (!m_need_trace)
return;

File diff suppressed because it is too large Load Diff