8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 00:03: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,
StreamType newStream, bool remap);
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);
static void pass1Validations(thread_db* tdbb, CompilerScratch* csb, Array<ValidateInfo>& validations);
static void postTriggerAccess(CompilerScratch* csb, jrd_rel* ownerRelation,
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);
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)
priv |= SCL_select;
const trig_vec* trigger = relation->rel_pre_erase ?
relation->rel_pre_erase : relation->rel_post_erase;
RefPtr<const TrigVector> trigger(relation->rel_pre_erase ?
relation->rel_pre_erase : relation->rel_post_erase);
// 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)
priv |= SCL_select;
const trig_vec* trigger = (relation->rel_pre_modify) ?
relation->rel_pre_modify : relation->rel_post_modify;
RefPtr<const TrigVector> trigger(relation->rel_pre_modify ?
relation->rel_pre_modify : relation->rel_post_modify);
// 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);
const trig_vec* trigger = relation->rel_pre_store ?
relation->rel_pre_store : relation->rel_post_store;
RefPtr<const TrigVector> trigger(relation->rel_pre_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
// 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 simple relation, return NULL.
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)
{
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.
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)
{
if (!tdbb->getTransaction()->tra_rpblist)

View File

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

View File

@ -77,7 +77,7 @@ namespace Jrd
class jrd_rel;
class jrd_prc;
class Trigger;
typedef Firebird::ObjectsArray<Trigger> trig_vec;
class TrigVector;
class Function;
class JrdStatement;
class Validation;
@ -292,8 +292,8 @@ public:
vec<jrd_rel*>* att_relations; // relation vector
Firebird::Array<jrd_prc*> att_procedures; // scanned procedures
trig_vec* att_triggers[DB_TRIGGER_MAX];
trig_vec* att_ddl_triggers;
TrigVector* att_triggers[DB_TRIGGER_MAX];
TrigVector* att_ddl_triggers;
Firebird::Array<Function*> att_functions; // User defined functions
Firebird::Array<JrdStatement*> att_internal; // internal statements
@ -556,7 +556,6 @@ private:
void destroy(Attachment* attachment);
};
} // namespace Jrd
#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.
void JrdStatement::verifyTriggerAccess(thread_db* tdbb, jrd_rel* ownerRelation,
trig_vec* triggers, jrd_rel* view)
TrigVector* triggers, jrd_rel* view)
{
if (!triggers)
return;
@ -640,7 +640,7 @@ void JrdStatement::verifyTriggerAccess(thread_db* tdbb, jrd_rel* ownerRelation,
// Invoke buildExternalAccess for triggers in vector
inline void JrdStatement::triggersExternalAccess(thread_db* tdbb, ExternalAccessList& list,
trig_vec* tvec)
TrigVector* tvec)
{
if (!tvec)
return;
@ -687,7 +687,7 @@ void JrdStatement::buildExternalAccess(thread_db* tdbb, ExternalAccessList& list
if (!relation)
continue;
trig_vec *vec1, *vec2;
RefPtr<TrigVector> vec1, vec2;
switch (item->exa_action)
{

View File

@ -57,9 +57,9 @@ public:
void release(thread_db* tdbb);
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);
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);

View File

@ -273,7 +273,7 @@ void jrd_rel::RelPagesSnapshot::clear()
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.
{
rel_pre_erase,

View File

@ -257,12 +257,12 @@ public:
Lock* rel_gc_lock; // garbage collection lock
IndexLock* rel_index_locks; // index existence locks
IndexBlock* rel_index_blocks; // index blocks for caching index info
trig_vec* rel_pre_erase; // Pre-operation erase trigger
trig_vec* rel_post_erase; // Post-operation erase trigger
trig_vec* rel_pre_modify; // Pre-operation modify trigger
trig_vec* rel_post_modify; // Post-operation modify trigger
trig_vec* rel_pre_store; // Pre-operation store trigger
trig_vec* rel_post_store; // Post-operation store trigger
TrigVector* rel_pre_erase; // Pre-operation erase trigger
TrigVector* rel_post_erase; // Post-operation erase trigger
TrigVector* rel_pre_modify; // Pre-operation modify trigger
TrigVector* rel_post_modify; // Post-operation modify trigger
TrigVector* rel_pre_store; // Pre-operation store trigger
TrigVector* rel_post_store; // Post-operation store trigger
prim rel_primary_dpnds; // foreign dependencies on this relation's primary key
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 void get_array_desc(thread_db*, const TEXT*, Ods::InternalArrayDesc*);
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 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 setup_array(thread_db*, blb*, const TEXT*, USHORT, TemporaryField*);
static blb* setup_triggers(thread_db*, jrd_rel*, bool, trig_vec**, blb*);
static void setup_trigger_details(thread_db*, jrd_rel*, blb*, trig_vec**, const TEXT*, bool);
static blb* setup_triggers(thread_db*, jrd_rel*, bool, TrigVector**, blb*);
static void setup_trigger_details(thread_db*, jrd_rel*, blb*, TrigVector**, const TEXT*, bool);
static bool validate_text_type (thread_db*, const TemporaryField*);
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.
*
**************************************/
trig_vec* tmp_vector;
TrigVector* tmp_vector;
tmp_vector = relation->rel_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;
bool external_flag = false;
bool computed_field;
trig_vec* triggers[TRIGGER_MAX];
TrigVector* triggers[TRIGGER_MAX];
SET_TDBB(tdbb);
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;
MET_scan_relation(tdbb, relation);
trig_vec* triggers[TRIGGER_MAX];
TrigVector* triggers[TRIGGER_MAX];
for (int i = 0; i < TRIGGER_MAX; ++i)
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,
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,
jrd_rel* relation,
blb* blob,
trig_vec** triggers,
TrigVector** triggers,
const TEXT* trigger_name,
bool null_view)
{

View File

@ -544,10 +544,10 @@ void EXE_execute_ddl_triggers(thread_db* tdbb, jrd_tra* transaction, bool preTri
try
{
trig_vec triggers;
trig_vec* triggersPtr = &triggers;
TrigVector 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)
{
@ -988,7 +988,7 @@ static void execute_looper(thread_db* tdbb,
void EXE_execute_triggers(thread_db* tdbb,
trig_vec** triggers,
TrigVector** triggers,
record_param* old_rpb,
record_param* new_rpb,
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_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 new_rec = new_rpb ? new_rpb->rpb_record : NULL;
@ -1038,7 +1038,7 @@ void EXE_execute_triggers(thread_db* tdbb,
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);

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* 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);
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
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())
{
// Start a transaction to execute ON CONNECT triggers.
@ -6902,7 +6902,7 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign
{
try
{
const trig_vec* const trig_disconnect =
const TrigVector* const trig_disconnect =
attachment->att_triggers[DB_TRIGGER_DISCONNECT];
if (!forcedPurge &&
@ -8077,3 +8077,29 @@ void JRD_cancel_operation(thread_db* /*tdbb*/, Jrd::Attachment* attachment, int
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 MessageNode;
// The database block, the topmost block in the metadata
// cache for a database
// 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
//

View File

@ -114,7 +114,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*, 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*);
static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*);
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 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*, 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 bid*);
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
static void release_cached_triggers(thread_db* tdbb, trig_vec* vector)
static void release_cached_triggers(thread_db* tdbb, TrigVector* vector)
{
if (!vector)
return;
@ -179,7 +179,7 @@ static void inc_int_use_count(JrdStatement* statement)
// 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)
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)
trig_vec(*attachment->att_pool);
TrigVector(*attachment->att_pool);
attachment->att_triggers[type]->addRef();
AutoRequest trigger_request;
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)
trig_vec(*attachment->att_pool);
TrigVector(*attachment->att_pool);
AutoRequest trigger_request;
@ -1907,7 +1908,7 @@ void MET_load_ddl_triggers(thread_db* tdbb)
void MET_load_trigger(thread_db* tdbb,
jrd_rel* relation,
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 TEXT* name = TRG.RDB$TRIGGER_NAME;
trig_vec** ptr;
TrigVector** ptr;
switch (type)
{
@ -3753,7 +3754,7 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
*
**************************************/
SET_TDBB(tdbb);
trig_vec* triggers[TRIGGER_MAX];
TrigVector* triggers[TRIGGER_MAX];
Attachment* attachment = tdbb->getAttachment();
Database* dbb = tdbb->getDatabase();
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.
// 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;
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,
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,
bool sys_trigger, USHORT flags,
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)
return;
trig_vec& vector = **vector_ptr;
TrigVector& vector = **vector_ptr;
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.
*
**************************************/
trig_vec* vector = *vector_ptr;
TrigVector* vector = *vector_ptr;
if (!vector)
return;
@ -4711,16 +4712,7 @@ void MET_release_triggers( thread_db* tdbb, trig_vec** vector_ptr)
return;
}
for (FB_SIZE_T i = 0; i < vector->getCount(); i++)
{
JrdStatement* stmt = (*vector)[i].statement;
if (stmt)
stmt->release(tdbb);
delete (*vector)[i].extTrigger;
}
delete vector;
vector->release(tdbb);
}
@ -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,
const TEXT* name, FB_UINT64 type,
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();
trig_vec* vector = *ptr;
TrigVector* vector = *ptr;
if (!vector)
{
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;
}
@ -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)
{
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)
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_ddl_triggers(Jrd::thread_db* tdbb);
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_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*);
@ -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_rel* MET_relation(Jrd::thread_db*, USHORT);
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_triggers(Jrd::thread_db*, Jrd::trig_vec**);
void MET_release_trigger(Jrd::thread_db*, Jrd::TrigVector**, const Firebird::MetaName&);
void MET_release_triggers(Jrd::thread_db*, Jrd::TrigVector**);
#ifdef DEV_BUILD
void MET_verify_cache(Jrd::thread_db*);
#endif