mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 03:23:03 +01:00
Backported fix for CORE-5428: Rare segfault when preparing request working with a table with triggers
This commit is contained in:
parent
1d27cdbabd
commit
0ca6c0dc2f
@ -87,12 +87,12 @@ static void makeValidation(thread_db* tdbb, CompilerScratch* csb, StreamType str
|
|||||||
static StmtNode* pass1ExpandView(thread_db* tdbb, CompilerScratch* csb, StreamType orgStream,
|
static StmtNode* pass1ExpandView(thread_db* tdbb, CompilerScratch* csb, StreamType orgStream,
|
||||||
StreamType newStream, bool remap);
|
StreamType newStream, bool remap);
|
||||||
static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jrd_rel* relation,
|
static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jrd_rel* relation,
|
||||||
const trig_vec* trigger, StreamType stream, StreamType updateStream, SecurityClass::flags_t priv,
|
const TrigVector* trigger, StreamType stream, StreamType updateStream, SecurityClass::flags_t priv,
|
||||||
jrd_rel* view, StreamType viewStream, StreamType viewUpdateStream);
|
jrd_rel* view, StreamType viewStream, StreamType viewUpdateStream);
|
||||||
static void pass1Validations(thread_db* tdbb, CompilerScratch* csb, Array<ValidateInfo>& validations);
|
static void pass1Validations(thread_db* tdbb, CompilerScratch* csb, Array<ValidateInfo>& validations);
|
||||||
static void postTriggerAccess(CompilerScratch* csb, jrd_rel* ownerRelation,
|
static void postTriggerAccess(CompilerScratch* csb, jrd_rel* ownerRelation,
|
||||||
ExternalAccess::exa_act operation, jrd_rel* view);
|
ExternalAccess::exa_act operation, jrd_rel* view);
|
||||||
static void preModifyEraseTriggers(thread_db* tdbb, trig_vec** trigs,
|
static void preModifyEraseTriggers(thread_db* tdbb, TrigVector** trigs,
|
||||||
StmtNode::WhichTrigger whichTrig, record_param* rpb, record_param* rec, TriggerAction op);
|
StmtNode::WhichTrigger whichTrig, record_param* rpb, record_param* rec, TriggerAction op);
|
||||||
static void validateExpressions(thread_db* tdbb, const Array<ValidateInfo>& validations);
|
static void validateExpressions(thread_db* tdbb, const Array<ValidateInfo>& validations);
|
||||||
|
|
||||||
@ -2224,8 +2224,8 @@ void EraseNode::pass1Erase(thread_db* tdbb, CompilerScratch* csb, EraseNode* nod
|
|||||||
if (parent)
|
if (parent)
|
||||||
priv |= SCL_select;
|
priv |= SCL_select;
|
||||||
|
|
||||||
const trig_vec* trigger = relation->rel_pre_erase ?
|
RefPtr<const TrigVector> trigger(relation->rel_pre_erase ?
|
||||||
relation->rel_pre_erase : relation->rel_post_erase;
|
relation->rel_pre_erase : relation->rel_post_erase);
|
||||||
|
|
||||||
// If we have a view with triggers, let's expand it.
|
// If we have a view with triggers, let's expand it.
|
||||||
|
|
||||||
@ -5928,8 +5928,8 @@ void ModifyNode::pass1Modify(thread_db* tdbb, CompilerScratch* csb, ModifyNode*
|
|||||||
if (parent)
|
if (parent)
|
||||||
priv |= SCL_select;
|
priv |= SCL_select;
|
||||||
|
|
||||||
const trig_vec* trigger = (relation->rel_pre_modify) ?
|
RefPtr<const TrigVector> trigger(relation->rel_pre_modify ?
|
||||||
relation->rel_pre_modify : relation->rel_post_modify;
|
relation->rel_pre_modify : relation->rel_post_modify);
|
||||||
|
|
||||||
// If we have a view with triggers, let's expand it.
|
// If we have a view with triggers, let's expand it.
|
||||||
|
|
||||||
@ -6693,8 +6693,8 @@ bool StoreNode::pass1Store(thread_db* tdbb, CompilerScratch* csb, StoreNode* nod
|
|||||||
|
|
||||||
postTriggerAccess(csb, relation, ExternalAccess::exa_insert, view);
|
postTriggerAccess(csb, relation, ExternalAccess::exa_insert, view);
|
||||||
|
|
||||||
const trig_vec* trigger = relation->rel_pre_store ?
|
RefPtr<const TrigVector> trigger(relation->rel_pre_store ?
|
||||||
relation->rel_pre_store : relation->rel_post_store;
|
relation->rel_pre_store : relation->rel_post_store);
|
||||||
|
|
||||||
// Check out insert. If this is an insert thru a view, verify the view by checking for read
|
// Check out insert. If this is an insert thru a view, verify the view by checking for read
|
||||||
// access on the base table. If field-level select privileges are implemented, this needs
|
// access on the base table. If field-level select privileges are implemented, this needs
|
||||||
@ -9092,7 +9092,7 @@ static StmtNode* pass1ExpandView(thread_db* tdbb, CompilerScratch* csb, StreamTy
|
|||||||
// If it's a view update, make sure the view is updatable, and return the view source for redirection.
|
// If it's a view update, make sure the view is updatable, and return the view source for redirection.
|
||||||
// If it's a simple relation, return NULL.
|
// If it's a simple relation, return NULL.
|
||||||
static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jrd_rel* relation,
|
static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jrd_rel* relation,
|
||||||
const trig_vec* trigger, StreamType stream, StreamType updateStream, SecurityClass::flags_t priv,
|
const TrigVector* trigger, StreamType stream, StreamType updateStream, SecurityClass::flags_t priv,
|
||||||
jrd_rel* view, StreamType viewStream, StreamType viewUpdateStream)
|
jrd_rel* view, StreamType viewStream, StreamType viewUpdateStream)
|
||||||
{
|
{
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
@ -9219,7 +9219,7 @@ static void postTriggerAccess(CompilerScratch* csb, jrd_rel* ownerRelation,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform operation's pre-triggers, storing active rpb in chain.
|
// Perform operation's pre-triggers, storing active rpb in chain.
|
||||||
static void preModifyEraseTriggers(thread_db* tdbb, trig_vec** trigs,
|
static void preModifyEraseTriggers(thread_db* tdbb, TrigVector** trigs,
|
||||||
StmtNode::WhichTrigger whichTrig, record_param* rpb, record_param* rec, TriggerAction op)
|
StmtNode::WhichTrigger whichTrig, record_param* rpb, record_param* rec, TriggerAction op)
|
||||||
{
|
{
|
||||||
if (!tdbb->getTransaction()->tra_rpblist)
|
if (!tdbb->getTransaction()->tra_rpblist)
|
||||||
|
@ -758,3 +758,4 @@ JAttachment* Attachment::getInterface() throw()
|
|||||||
{
|
{
|
||||||
return att_stable->getInterface();
|
return att_stable->getInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ namespace Jrd
|
|||||||
class jrd_rel;
|
class jrd_rel;
|
||||||
class jrd_prc;
|
class jrd_prc;
|
||||||
class Trigger;
|
class Trigger;
|
||||||
typedef Firebird::ObjectsArray<Trigger> trig_vec;
|
class TrigVector;
|
||||||
class Function;
|
class Function;
|
||||||
class JrdStatement;
|
class JrdStatement;
|
||||||
class Validation;
|
class Validation;
|
||||||
@ -292,8 +292,8 @@ public:
|
|||||||
|
|
||||||
vec<jrd_rel*>* att_relations; // relation vector
|
vec<jrd_rel*>* att_relations; // relation vector
|
||||||
Firebird::Array<jrd_prc*> att_procedures; // scanned procedures
|
Firebird::Array<jrd_prc*> att_procedures; // scanned procedures
|
||||||
trig_vec* att_triggers[DB_TRIGGER_MAX];
|
TrigVector* att_triggers[DB_TRIGGER_MAX];
|
||||||
trig_vec* att_ddl_triggers;
|
TrigVector* att_ddl_triggers;
|
||||||
Firebird::Array<Function*> att_functions; // User defined functions
|
Firebird::Array<Function*> att_functions; // User defined functions
|
||||||
|
|
||||||
Firebird::Array<JrdStatement*> att_internal; // internal statements
|
Firebird::Array<JrdStatement*> att_internal; // internal statements
|
||||||
@ -556,7 +556,6 @@ private:
|
|||||||
void destroy(Attachment* attachment);
|
void destroy(Attachment* attachment);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace Jrd
|
} // namespace Jrd
|
||||||
|
|
||||||
#endif // JRD_ATTACHMENT_H
|
#endif // JRD_ATTACHMENT_H
|
||||||
|
@ -588,7 +588,7 @@ void JrdStatement::release(thread_db* tdbb)
|
|||||||
|
|
||||||
// Check that we have enough rights to access all resources this list of triggers touches.
|
// Check that we have enough rights to access all resources this list of triggers touches.
|
||||||
void JrdStatement::verifyTriggerAccess(thread_db* tdbb, jrd_rel* ownerRelation,
|
void JrdStatement::verifyTriggerAccess(thread_db* tdbb, jrd_rel* ownerRelation,
|
||||||
trig_vec* triggers, jrd_rel* view)
|
TrigVector* triggers, jrd_rel* view)
|
||||||
{
|
{
|
||||||
if (!triggers)
|
if (!triggers)
|
||||||
return;
|
return;
|
||||||
@ -640,7 +640,7 @@ void JrdStatement::verifyTriggerAccess(thread_db* tdbb, jrd_rel* ownerRelation,
|
|||||||
|
|
||||||
// Invoke buildExternalAccess for triggers in vector
|
// Invoke buildExternalAccess for triggers in vector
|
||||||
inline void JrdStatement::triggersExternalAccess(thread_db* tdbb, ExternalAccessList& list,
|
inline void JrdStatement::triggersExternalAccess(thread_db* tdbb, ExternalAccessList& list,
|
||||||
trig_vec* tvec)
|
TrigVector* tvec)
|
||||||
{
|
{
|
||||||
if (!tvec)
|
if (!tvec)
|
||||||
return;
|
return;
|
||||||
@ -687,7 +687,7 @@ void JrdStatement::buildExternalAccess(thread_db* tdbb, ExternalAccessList& list
|
|||||||
if (!relation)
|
if (!relation)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
trig_vec *vec1, *vec2;
|
RefPtr<TrigVector> vec1, vec2;
|
||||||
|
|
||||||
switch (item->exa_action)
|
switch (item->exa_action)
|
||||||
{
|
{
|
||||||
|
@ -57,9 +57,9 @@ public:
|
|||||||
void release(thread_db* tdbb);
|
void release(thread_db* tdbb);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void verifyTriggerAccess(thread_db* tdbb, jrd_rel* ownerRelation, trig_vec* triggers,
|
static void verifyTriggerAccess(thread_db* tdbb, jrd_rel* ownerRelation, TrigVector* triggers,
|
||||||
jrd_rel* view);
|
jrd_rel* view);
|
||||||
static void triggersExternalAccess(thread_db* tdbb, ExternalAccessList& list, trig_vec* tvec);
|
static void triggersExternalAccess(thread_db* tdbb, ExternalAccessList& list, TrigVector* tvec);
|
||||||
|
|
||||||
void buildExternalAccess(thread_db* tdbb, ExternalAccessList& list);
|
void buildExternalAccess(thread_db* tdbb, ExternalAccessList& list);
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ void jrd_rel::RelPagesSnapshot::clear()
|
|||||||
|
|
||||||
bool jrd_rel::hasTriggers() const
|
bool jrd_rel::hasTriggers() const
|
||||||
{
|
{
|
||||||
typedef const trig_vec* ctv;
|
typedef const TrigVector* ctv;
|
||||||
ctv trigs[6] = // non-const array, don't want optimization tricks by the compiler.
|
ctv trigs[6] = // non-const array, don't want optimization tricks by the compiler.
|
||||||
{
|
{
|
||||||
rel_pre_erase,
|
rel_pre_erase,
|
||||||
|
@ -257,12 +257,12 @@ public:
|
|||||||
Lock* rel_gc_lock; // garbage collection lock
|
Lock* rel_gc_lock; // garbage collection lock
|
||||||
IndexLock* rel_index_locks; // index existence locks
|
IndexLock* rel_index_locks; // index existence locks
|
||||||
IndexBlock* rel_index_blocks; // index blocks for caching index info
|
IndexBlock* rel_index_blocks; // index blocks for caching index info
|
||||||
trig_vec* rel_pre_erase; // Pre-operation erase trigger
|
TrigVector* rel_pre_erase; // Pre-operation erase trigger
|
||||||
trig_vec* rel_post_erase; // Post-operation erase trigger
|
TrigVector* rel_post_erase; // Post-operation erase trigger
|
||||||
trig_vec* rel_pre_modify; // Pre-operation modify trigger
|
TrigVector* rel_pre_modify; // Pre-operation modify trigger
|
||||||
trig_vec* rel_post_modify; // Post-operation modify trigger
|
TrigVector* rel_post_modify; // Post-operation modify trigger
|
||||||
trig_vec* rel_pre_store; // Pre-operation store trigger
|
TrigVector* rel_pre_store; // Pre-operation store trigger
|
||||||
trig_vec* rel_post_store; // Post-operation store trigger
|
TrigVector* rel_post_store; // Post-operation store trigger
|
||||||
prim rel_primary_dpnds; // foreign dependencies on this relation's primary key
|
prim rel_primary_dpnds; // foreign dependencies on this relation's primary key
|
||||||
frgn rel_foreign_refs; // foreign references to other relations' primary keys
|
frgn rel_foreign_refs; // foreign references to other relations' primary keys
|
||||||
|
|
||||||
|
@ -498,13 +498,13 @@ static bool formatsAreEqual(const Format*, const Format*);
|
|||||||
static bool find_depend_in_dfw(thread_db*, TEXT*, USHORT, USHORT, jrd_tra*);
|
static bool find_depend_in_dfw(thread_db*, TEXT*, USHORT, USHORT, jrd_tra*);
|
||||||
static void get_array_desc(thread_db*, const TEXT*, Ods::InternalArrayDesc*);
|
static void get_array_desc(thread_db*, const TEXT*, Ods::InternalArrayDesc*);
|
||||||
static void get_trigger_dependencies(DeferredWork*, bool, jrd_tra*);
|
static void get_trigger_dependencies(DeferredWork*, bool, jrd_tra*);
|
||||||
static void load_trigs(thread_db*, jrd_rel*, trig_vec**);
|
static void load_trigs(thread_db*, jrd_rel*, TrigVector**);
|
||||||
static Format* make_format(thread_db*, jrd_rel*, USHORT *, TemporaryField*);
|
static Format* make_format(thread_db*, jrd_rel*, USHORT *, TemporaryField*);
|
||||||
static void put_summary_blob(thread_db* tdbb, blb*, enum rsr_t, bid*, jrd_tra*);
|
static void put_summary_blob(thread_db* tdbb, blb*, enum rsr_t, bid*, jrd_tra*);
|
||||||
static void put_summary_record(thread_db* tdbb, blb*, enum rsr_t, const UCHAR*, USHORT);
|
static void put_summary_record(thread_db* tdbb, blb*, enum rsr_t, const UCHAR*, USHORT);
|
||||||
static void setup_array(thread_db*, blb*, const TEXT*, USHORT, TemporaryField*);
|
static void setup_array(thread_db*, blb*, const TEXT*, USHORT, TemporaryField*);
|
||||||
static blb* setup_triggers(thread_db*, jrd_rel*, bool, trig_vec**, blb*);
|
static blb* setup_triggers(thread_db*, jrd_rel*, bool, TrigVector**, blb*);
|
||||||
static void setup_trigger_details(thread_db*, jrd_rel*, blb*, trig_vec**, const TEXT*, bool);
|
static void setup_trigger_details(thread_db*, jrd_rel*, blb*, TrigVector**, const TEXT*, bool);
|
||||||
static bool validate_text_type (thread_db*, const TemporaryField*);
|
static bool validate_text_type (thread_db*, const TemporaryField*);
|
||||||
|
|
||||||
static void check_partners(thread_db*, const USHORT);
|
static void check_partners(thread_db*, const USHORT);
|
||||||
@ -5329,7 +5329,7 @@ static void get_trigger_dependencies(DeferredWork* work, bool compile, jrd_tra*
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void load_trigs(thread_db* tdbb, jrd_rel* relation, trig_vec** triggers)
|
static void load_trigs(thread_db* tdbb, jrd_rel* relation, TrigVector** triggers)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -5343,7 +5343,7 @@ static void load_trigs(thread_db* tdbb, jrd_rel* relation, trig_vec** triggers)
|
|||||||
* place ie the relation block.
|
* place ie the relation block.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
trig_vec* tmp_vector;
|
TrigVector* tmp_vector;
|
||||||
|
|
||||||
tmp_vector = relation->rel_pre_store;
|
tmp_vector = relation->rel_pre_store;
|
||||||
relation->rel_pre_store = triggers[TRIGGER_PRE_STORE];
|
relation->rel_pre_store = triggers[TRIGGER_PRE_STORE];
|
||||||
@ -5574,7 +5574,7 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
|||||||
int physical_fields = 0;
|
int physical_fields = 0;
|
||||||
bool external_flag = false;
|
bool external_flag = false;
|
||||||
bool computed_field;
|
bool computed_field;
|
||||||
trig_vec* triggers[TRIGGER_MAX];
|
TrigVector* triggers[TRIGGER_MAX];
|
||||||
|
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||||
@ -6042,7 +6042,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
|
|||||||
relation->rel_flags &= ~REL_scanned;
|
relation->rel_flags &= ~REL_scanned;
|
||||||
MET_scan_relation(tdbb, relation);
|
MET_scan_relation(tdbb, relation);
|
||||||
|
|
||||||
trig_vec* triggers[TRIGGER_MAX];
|
TrigVector* triggers[TRIGGER_MAX];
|
||||||
|
|
||||||
for (int i = 0; i < TRIGGER_MAX; ++i)
|
for (int i = 0; i < TRIGGER_MAX; ++i)
|
||||||
triggers[i] = NULL;
|
triggers[i] = NULL;
|
||||||
@ -6276,7 +6276,7 @@ static void setup_array(thread_db* tdbb, blb* blob, const TEXT* field_name, USHO
|
|||||||
|
|
||||||
|
|
||||||
static blb* setup_triggers(thread_db* tdbb, jrd_rel* relation, bool null_view,
|
static blb* setup_triggers(thread_db* tdbb, jrd_rel* relation, bool null_view,
|
||||||
trig_vec** triggers, blb* blob)
|
TrigVector** triggers, blb* blob)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -6374,7 +6374,7 @@ static blb* setup_triggers(thread_db* tdbb, jrd_rel* relation, bool null_view,
|
|||||||
static void setup_trigger_details(thread_db* tdbb,
|
static void setup_trigger_details(thread_db* tdbb,
|
||||||
jrd_rel* relation,
|
jrd_rel* relation,
|
||||||
blb* blob,
|
blb* blob,
|
||||||
trig_vec** triggers,
|
TrigVector** triggers,
|
||||||
const TEXT* trigger_name,
|
const TEXT* trigger_name,
|
||||||
bool null_view)
|
bool null_view)
|
||||||
{
|
{
|
||||||
|
@ -544,10 +544,10 @@ void EXE_execute_ddl_triggers(thread_db* tdbb, jrd_tra* transaction, bool preTri
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
trig_vec triggers;
|
TrigVector triggers;
|
||||||
trig_vec* triggersPtr = &triggers;
|
TrigVector* triggersPtr = &triggers;
|
||||||
|
|
||||||
for (trig_vec::iterator i = attachment->att_ddl_triggers->begin();
|
for (TrigVector::iterator i = attachment->att_ddl_triggers->begin();
|
||||||
i != attachment->att_ddl_triggers->end();
|
i != attachment->att_ddl_triggers->end();
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
@ -988,7 +988,7 @@ static void execute_looper(thread_db* tdbb,
|
|||||||
|
|
||||||
|
|
||||||
void EXE_execute_triggers(thread_db* tdbb,
|
void EXE_execute_triggers(thread_db* tdbb,
|
||||||
trig_vec** triggers,
|
TrigVector** triggers,
|
||||||
record_param* old_rpb,
|
record_param* old_rpb,
|
||||||
record_param* new_rpb,
|
record_param* new_rpb,
|
||||||
TriggerAction trigger_action, StmtNode::WhichTrigger which_trig)
|
TriggerAction trigger_action, StmtNode::WhichTrigger which_trig)
|
||||||
@ -1012,7 +1012,7 @@ void EXE_execute_triggers(thread_db* tdbb,
|
|||||||
jrd_req* const request = tdbb->getRequest();
|
jrd_req* const request = tdbb->getRequest();
|
||||||
jrd_tra* const transaction = request ? request->req_transaction : tdbb->getTransaction();
|
jrd_tra* const transaction = request ? request->req_transaction : tdbb->getTransaction();
|
||||||
|
|
||||||
trig_vec* vector = *triggers;
|
TrigVector* vector = *triggers;
|
||||||
Record* const old_rec = old_rpb ? old_rpb->rpb_record : NULL;
|
Record* const old_rec = old_rpb ? old_rpb->rpb_record : NULL;
|
||||||
Record* const new_rec = new_rpb ? new_rpb->rpb_record : NULL;
|
Record* const new_rec = new_rpb ? new_rpb->rpb_record : NULL;
|
||||||
|
|
||||||
@ -1038,7 +1038,7 @@ void EXE_execute_triggers(thread_db* tdbb,
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (trig_vec::iterator ptr = vector->begin(); ptr != vector->end(); ++ptr)
|
for (TrigVector::iterator ptr = vector->begin(); ptr != vector->end(); ++ptr)
|
||||||
{
|
{
|
||||||
ptr->compile(tdbb);
|
ptr->compile(tdbb);
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ void EXE_execute_ddl_triggers(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction,
|
|||||||
const Jrd::StmtNode* EXE_looper(Jrd::thread_db* tdbb, Jrd::jrd_req* request,
|
const Jrd::StmtNode* EXE_looper(Jrd::thread_db* tdbb, Jrd::jrd_req* request,
|
||||||
const Jrd::StmtNode* in_node);
|
const Jrd::StmtNode* in_node);
|
||||||
|
|
||||||
void EXE_execute_triggers(Jrd::thread_db*, Jrd::trig_vec**, Jrd::record_param*, Jrd::record_param*,
|
void EXE_execute_triggers(Jrd::thread_db*, Jrd::TrigVector**, Jrd::record_param*, Jrd::record_param*,
|
||||||
enum TriggerAction, Jrd::StmtNode::WhichTrigger);
|
enum TriggerAction, Jrd::StmtNode::WhichTrigger);
|
||||||
|
|
||||||
void EXE_receive(Jrd::thread_db*, Jrd::jrd_req*, USHORT, ULONG, UCHAR*, bool = false);
|
void EXE_receive(Jrd::thread_db*, Jrd::jrd_req*, USHORT, ULONG, UCHAR*, bool = false);
|
||||||
|
@ -1869,7 +1869,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
|
|||||||
// load DDL triggers
|
// load DDL triggers
|
||||||
MET_load_ddl_triggers(tdbb);
|
MET_load_ddl_triggers(tdbb);
|
||||||
|
|
||||||
const trig_vec* trig_connect = attachment->att_triggers[DB_TRIGGER_CONNECT];
|
const TrigVector* trig_connect = attachment->att_triggers[DB_TRIGGER_CONNECT];
|
||||||
if (trig_connect && !trig_connect->isEmpty())
|
if (trig_connect && !trig_connect->isEmpty())
|
||||||
{
|
{
|
||||||
// Start a transaction to execute ON CONNECT triggers.
|
// Start a transaction to execute ON CONNECT triggers.
|
||||||
@ -6902,7 +6902,7 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const trig_vec* const trig_disconnect =
|
const TrigVector* const trig_disconnect =
|
||||||
attachment->att_triggers[DB_TRIGGER_DISCONNECT];
|
attachment->att_triggers[DB_TRIGGER_DISCONNECT];
|
||||||
|
|
||||||
if (!forcedPurge &&
|
if (!forcedPurge &&
|
||||||
@ -8077,3 +8077,29 @@ void JRD_cancel_operation(thread_db* /*tdbb*/, Jrd::Attachment* attachment, int
|
|||||||
fb_assert(false);
|
fb_assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TrigVector::release() const
|
||||||
|
{
|
||||||
|
release(JRD_get_thread_data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TrigVector::release(thread_db* tdbb) const
|
||||||
|
{
|
||||||
|
if (--useCount == 0)
|
||||||
|
{
|
||||||
|
const const_iterator e = end();
|
||||||
|
for (const_iterator t = begin(); t != e; ++t)
|
||||||
|
{
|
||||||
|
JrdStatement* stmt = t->statement;
|
||||||
|
if (stmt)
|
||||||
|
stmt->release(tdbb);
|
||||||
|
|
||||||
|
delete t->extTrigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -135,8 +135,6 @@ class PreparedStatement;
|
|||||||
class TraceManager;
|
class TraceManager;
|
||||||
class MessageNode;
|
class MessageNode;
|
||||||
|
|
||||||
// The database block, the topmost block in the metadata
|
|
||||||
// cache for a database
|
|
||||||
|
|
||||||
// Relation trigger definition
|
// Relation trigger definition
|
||||||
|
|
||||||
@ -172,6 +170,39 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Array of triggers (suppose separate arrays for triggers of different types)
|
||||||
|
|
||||||
|
class TrigVector : public Firebird::ObjectsArray<Trigger>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TrigVector(Firebird::MemoryPool& pool)
|
||||||
|
: Firebird::ObjectsArray<Trigger>(pool),
|
||||||
|
useCount(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
TrigVector()
|
||||||
|
: Firebird::ObjectsArray<Trigger>(),
|
||||||
|
useCount(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void addRef() const
|
||||||
|
{
|
||||||
|
++useCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() const;
|
||||||
|
void release(thread_db* tdbb) const;
|
||||||
|
|
||||||
|
~TrigVector()
|
||||||
|
{
|
||||||
|
fb_assert(useCount.value() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable Firebird::AtomicCounter useCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flags to indicate normal internal requests vs. dyn internal requests
|
// Flags to indicate normal internal requests vs. dyn internal requests
|
||||||
//
|
//
|
||||||
|
@ -114,7 +114,7 @@ static int blocking_ast_relation(void*);
|
|||||||
static int partners_ast_relation(void*);
|
static int partners_ast_relation(void*);
|
||||||
static int rescan_ast_relation(void*);
|
static int rescan_ast_relation(void*);
|
||||||
static ULONG get_rel_flags_from_FLAGS(USHORT);
|
static ULONG get_rel_flags_from_FLAGS(USHORT);
|
||||||
static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, trig_vec**, const TEXT*, FB_UINT64, bool,
|
static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, TrigVector**, const TEXT*, FB_UINT64, bool,
|
||||||
USHORT, const MetaName&, const string&, const bid*);
|
USHORT, const MetaName&, const string&, const bid*);
|
||||||
static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*);
|
static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*);
|
||||||
static void lookup_view_contexts(thread_db*, jrd_rel*);
|
static void lookup_view_contexts(thread_db*, jrd_rel*);
|
||||||
@ -122,7 +122,7 @@ static void make_relation_scope_name(const TEXT*, const USHORT, string& str);
|
|||||||
static ValueExprNode* parse_field_default_blr(thread_db* tdbb, bid* blob_id);
|
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 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 bool resolve_charset_and_collation(thread_db*, USHORT*, const UCHAR*, const UCHAR*);
|
||||||
static void save_trigger_data(thread_db*, trig_vec**, jrd_rel*, JrdStatement*, blb*, blb*,
|
static void save_trigger_data(thread_db*, TrigVector**, jrd_rel*, JrdStatement*, blb*, blb*,
|
||||||
const TEXT*, FB_UINT64, bool, USHORT, const MetaName&, const string&,
|
const TEXT*, FB_UINT64, bool, USHORT, const MetaName&, const string&,
|
||||||
const bid*);
|
const bid*);
|
||||||
static void scan_partners(thread_db*, jrd_rel*);
|
static void scan_partners(thread_db*, jrd_rel*);
|
||||||
@ -132,7 +132,7 @@ static bool verify_TRG_ignore_perm(thread_db*, const MetaName&);
|
|||||||
|
|
||||||
|
|
||||||
// Decompile all triggers from vector
|
// Decompile all triggers from vector
|
||||||
static void release_cached_triggers(thread_db* tdbb, trig_vec* vector)
|
static void release_cached_triggers(thread_db* tdbb, TrigVector* vector)
|
||||||
{
|
{
|
||||||
if (!vector)
|
if (!vector)
|
||||||
return;
|
return;
|
||||||
@ -179,7 +179,7 @@ static void inc_int_use_count(JrdStatement* statement)
|
|||||||
|
|
||||||
|
|
||||||
// Increment int_use_count for all procedures used by triggers
|
// Increment int_use_count for all procedures used by triggers
|
||||||
static void post_used_procedures(trig_vec* vector)
|
static void post_used_procedures(TrigVector* vector)
|
||||||
{
|
{
|
||||||
if (!vector)
|
if (!vector)
|
||||||
return;
|
return;
|
||||||
@ -1851,7 +1851,8 @@ void MET_load_db_triggers(thread_db* tdbb, int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
attachment->att_triggers[type] = FB_NEW_POOL(*attachment->att_pool)
|
attachment->att_triggers[type] = FB_NEW_POOL(*attachment->att_pool)
|
||||||
trig_vec(*attachment->att_pool);
|
TrigVector(*attachment->att_pool);
|
||||||
|
attachment->att_triggers[type]->addRef();
|
||||||
|
|
||||||
AutoRequest trigger_request;
|
AutoRequest trigger_request;
|
||||||
int encoded_type = type | TRIGGER_TYPE_DB;
|
int encoded_type = type | TRIGGER_TYPE_DB;
|
||||||
@ -1884,7 +1885,7 @@ void MET_load_ddl_triggers(thread_db* tdbb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
attachment->att_ddl_triggers = FB_NEW_POOL(*attachment->att_pool)
|
attachment->att_ddl_triggers = FB_NEW_POOL(*attachment->att_pool)
|
||||||
trig_vec(*attachment->att_pool);
|
TrigVector(*attachment->att_pool);
|
||||||
|
|
||||||
AutoRequest trigger_request;
|
AutoRequest trigger_request;
|
||||||
|
|
||||||
@ -1907,7 +1908,7 @@ void MET_load_ddl_triggers(thread_db* tdbb)
|
|||||||
void MET_load_trigger(thread_db* tdbb,
|
void MET_load_trigger(thread_db* tdbb,
|
||||||
jrd_rel* relation,
|
jrd_rel* relation,
|
||||||
const MetaName& trigger_name,
|
const MetaName& trigger_name,
|
||||||
trig_vec** triggers)
|
TrigVector** triggers)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -3117,7 +3118,7 @@ void MET_parse_sys_trigger(thread_db* tdbb, jrd_rel* relation)
|
|||||||
const USHORT trig_flags = TRG.RDB$FLAGS;
|
const USHORT trig_flags = TRG.RDB$FLAGS;
|
||||||
const TEXT* name = TRG.RDB$TRIGGER_NAME;
|
const TEXT* name = TRG.RDB$TRIGGER_NAME;
|
||||||
|
|
||||||
trig_vec** ptr;
|
TrigVector** ptr;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@ -3753,7 +3754,7 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
trig_vec* triggers[TRIGGER_MAX];
|
TrigVector* triggers[TRIGGER_MAX];
|
||||||
Attachment* attachment = tdbb->getAttachment();
|
Attachment* attachment = tdbb->getAttachment();
|
||||||
Database* dbb = tdbb->getDatabase();
|
Database* dbb = tdbb->getDatabase();
|
||||||
Jrd::ContextPoolHolder context(tdbb, attachment->att_pool);
|
Jrd::ContextPoolHolder context(tdbb, attachment->att_pool);
|
||||||
@ -4050,7 +4051,7 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
|
|||||||
// We have just loaded the triggers onto the local vector triggers.
|
// We have just loaded the triggers onto the local vector triggers.
|
||||||
// Its now time to place them at their rightful place ie the relation block.
|
// Its now time to place them at their rightful place ie the relation block.
|
||||||
|
|
||||||
trig_vec* tmp_vector;
|
TrigVector* tmp_vector;
|
||||||
|
|
||||||
tmp_vector = relation->rel_pre_store;
|
tmp_vector = relation->rel_pre_store;
|
||||||
relation->rel_pre_store = triggers[TRIGGER_PRE_STORE];
|
relation->rel_pre_store = triggers[TRIGGER_PRE_STORE];
|
||||||
@ -4443,7 +4444,7 @@ ULONG MET_get_rel_flags_from_TYPE(USHORT type)
|
|||||||
|
|
||||||
|
|
||||||
static void get_trigger(thread_db* tdbb, jrd_rel* relation,
|
static void get_trigger(thread_db* tdbb, jrd_rel* relation,
|
||||||
bid* blob_id, bid* debug_blob_id, trig_vec** ptr,
|
bid* blob_id, bid* debug_blob_id, TrigVector** ptr,
|
||||||
const TEXT* name, FB_UINT64 type,
|
const TEXT* name, FB_UINT64 type,
|
||||||
bool sys_trigger, USHORT flags,
|
bool sys_trigger, USHORT flags,
|
||||||
const MetaName& engine, const string& entryPoint,
|
const MetaName& engine, const string& entryPoint,
|
||||||
@ -4642,7 +4643,7 @@ static BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MET_release_trigger(thread_db* tdbb, trig_vec** vector_ptr, const MetaName& name)
|
void MET_release_trigger(thread_db* tdbb, TrigVector** vector_ptr, const MetaName& name)
|
||||||
{
|
{
|
||||||
/***********************************************
|
/***********************************************
|
||||||
*
|
*
|
||||||
@ -4659,7 +4660,7 @@ void MET_release_trigger(thread_db* tdbb, trig_vec** vector_ptr, const MetaName&
|
|||||||
if (!*vector_ptr)
|
if (!*vector_ptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
trig_vec& vector = **vector_ptr;
|
TrigVector& vector = **vector_ptr;
|
||||||
|
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
|
|
||||||
@ -4681,7 +4682,7 @@ void MET_release_trigger(thread_db* tdbb, trig_vec** vector_ptr, const MetaName&
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MET_release_triggers( thread_db* tdbb, trig_vec** vector_ptr)
|
void MET_release_triggers( thread_db* tdbb, TrigVector** vector_ptr)
|
||||||
{
|
{
|
||||||
/***********************************************
|
/***********************************************
|
||||||
*
|
*
|
||||||
@ -4695,7 +4696,7 @@ void MET_release_triggers( thread_db* tdbb, trig_vec** vector_ptr)
|
|||||||
* else do the work.
|
* else do the work.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
trig_vec* vector = *vector_ptr;
|
TrigVector* vector = *vector_ptr;
|
||||||
|
|
||||||
if (!vector)
|
if (!vector)
|
||||||
return;
|
return;
|
||||||
@ -4711,16 +4712,7 @@ void MET_release_triggers( thread_db* tdbb, trig_vec** vector_ptr)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FB_SIZE_T i = 0; i < vector->getCount(); i++)
|
vector->release(tdbb);
|
||||||
{
|
|
||||||
JrdStatement* stmt = (*vector)[i].statement;
|
|
||||||
if (stmt)
|
|
||||||
stmt->release(tdbb);
|
|
||||||
|
|
||||||
delete (*vector)[i].extTrigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete vector;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4837,7 +4829,7 @@ static bool resolve_charset_and_collation(thread_db* tdbb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void save_trigger_data(thread_db* tdbb, trig_vec** ptr, jrd_rel* relation,
|
static void save_trigger_data(thread_db* tdbb, TrigVector** ptr, jrd_rel* relation,
|
||||||
JrdStatement* statement, blb* blrBlob, blb* debugInfoBlob,
|
JrdStatement* statement, blb* blrBlob, blb* debugInfoBlob,
|
||||||
const TEXT* name, FB_UINT64 type,
|
const TEXT* name, FB_UINT64 type,
|
||||||
bool sys_trigger, USHORT flags,
|
bool sys_trigger, USHORT flags,
|
||||||
@ -4855,12 +4847,13 @@ static void save_trigger_data(thread_db* tdbb, trig_vec** ptr, jrd_rel* relation
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
Attachment* attachment = tdbb->getAttachment();
|
Attachment* attachment = tdbb->getAttachment();
|
||||||
trig_vec* vector = *ptr;
|
TrigVector* vector = *ptr;
|
||||||
|
|
||||||
if (!vector)
|
if (!vector)
|
||||||
{
|
{
|
||||||
MemoryPool* pool = relation ? relation->rel_pool : attachment->att_pool;
|
MemoryPool* pool = relation ? relation->rel_pool : attachment->att_pool;
|
||||||
vector = FB_NEW_POOL(*pool) trig_vec(*pool);
|
vector = FB_NEW_POOL(*pool) TrigVector(*pool);
|
||||||
|
vector->addRef();
|
||||||
*ptr = vector;
|
*ptr = vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4905,11 +4898,11 @@ static void save_trigger_data(thread_db* tdbb, trig_vec** ptr, jrd_rel* relation
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Trigger* findTrigger(trig_vec* triggers, const MetaName& trig_name)
|
const Trigger* findTrigger(TrigVector* triggers, const MetaName& trig_name)
|
||||||
{
|
{
|
||||||
if (triggers)
|
if (triggers)
|
||||||
{
|
{
|
||||||
for (trig_vec::iterator t = triggers->begin(); t != triggers->end(); ++t)
|
for (TrigVector::iterator t = triggers->begin(); t != triggers->end(); ++t)
|
||||||
{
|
{
|
||||||
if (t->name.compare(trig_name) == 0)
|
if (t->name.compare(trig_name) == 0)
|
||||||
return &(*t);
|
return &(*t);
|
||||||
|
@ -94,7 +94,7 @@ void MET_get_shadow_files(Jrd::thread_db*, bool);
|
|||||||
void MET_load_db_triggers(Jrd::thread_db*, int);
|
void MET_load_db_triggers(Jrd::thread_db*, int);
|
||||||
void MET_load_ddl_triggers(Jrd::thread_db* tdbb);
|
void MET_load_ddl_triggers(Jrd::thread_db* tdbb);
|
||||||
bool MET_load_exception(Jrd::thread_db*, Jrd::ExceptionItem&);
|
bool MET_load_exception(Jrd::thread_db*, Jrd::ExceptionItem&);
|
||||||
void MET_load_trigger(Jrd::thread_db*, Jrd::jrd_rel*, const Firebird::MetaName&, Jrd::trig_vec**);
|
void MET_load_trigger(Jrd::thread_db*, Jrd::jrd_rel*, const Firebird::MetaName&, Jrd::TrigVector**);
|
||||||
void MET_lookup_cnstrt_for_index(Jrd::thread_db*, Firebird::MetaName& constraint, const Firebird::MetaName& index_name);
|
void MET_lookup_cnstrt_for_index(Jrd::thread_db*, Firebird::MetaName& constraint, const Firebird::MetaName& index_name);
|
||||||
void MET_lookup_cnstrt_for_trigger(Jrd::thread_db*, Firebird::MetaName&, Firebird::MetaName&, const Firebird::MetaName&);
|
void MET_lookup_cnstrt_for_trigger(Jrd::thread_db*, Firebird::MetaName&, Firebird::MetaName&, const Firebird::MetaName&);
|
||||||
void MET_lookup_exception(Jrd::thread_db*, SLONG, /* OUT */ Firebird::MetaName&, /* OUT */ Firebird::string*);
|
void MET_lookup_exception(Jrd::thread_db*, SLONG, /* OUT */ Firebird::MetaName&, /* OUT */ Firebird::string*);
|
||||||
@ -120,8 +120,8 @@ void MET_prepare(Jrd::thread_db*, Jrd::jrd_tra*, USHORT, const UCHAR*);
|
|||||||
Jrd::jrd_prc* MET_procedure(Jrd::thread_db*, USHORT, bool, USHORT);
|
Jrd::jrd_prc* MET_procedure(Jrd::thread_db*, USHORT, bool, USHORT);
|
||||||
Jrd::jrd_rel* MET_relation(Jrd::thread_db*, USHORT);
|
Jrd::jrd_rel* MET_relation(Jrd::thread_db*, USHORT);
|
||||||
void MET_release_existence(Jrd::thread_db*, Jrd::jrd_rel*);
|
void MET_release_existence(Jrd::thread_db*, Jrd::jrd_rel*);
|
||||||
void MET_release_trigger(Jrd::thread_db*, Jrd::trig_vec**, const Firebird::MetaName&);
|
void MET_release_trigger(Jrd::thread_db*, Jrd::TrigVector**, const Firebird::MetaName&);
|
||||||
void MET_release_triggers(Jrd::thread_db*, Jrd::trig_vec**);
|
void MET_release_triggers(Jrd::thread_db*, Jrd::TrigVector**);
|
||||||
#ifdef DEV_BUILD
|
#ifdef DEV_BUILD
|
||||||
void MET_verify_cache(Jrd::thread_db*);
|
void MET_verify_cache(Jrd::thread_db*);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user