8
0
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:
AlexPeshkoff 2016-12-25 18:08:30 +03:00
parent 1d27cdbabd
commit 0ca6c0dc2f
14 changed files with 129 additions and 79 deletions

View File

@ -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)

View File

@ -758,3 +758,4 @@ JAttachment* Attachment::getInterface() throw()
{ {
return att_stable->getInterface(); return att_stable->getInterface();
} }

View File

@ -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

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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
// //

View File

@ -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);

View File

@ -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