diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp index 499dae91784..dc5f7b371c8 100644 --- a/src/jrd/exe.cpp +++ b/src/jrd/exe.cpp @@ -1157,6 +1157,17 @@ void EXE_execute_triggers(thread_db* tdbb, { for (TrigVector::iterator ptr = vector->begin(); ptr != vector->end(); ++ptr) { + // The system trigger that implement cascading action can be skipped if + // no PK/UK field have been changed by UPDATE. + + if ((which_trig == StmtNode::POST_TRIG) && (trigger_action == TRIGGER_UPDATE) && + (ptr->sysTrigger == fb_sysflag_referential_constraint)) + { + fb_assert(new_rpb); + if (!(new_rpb->rpb_runtime_flags & RPB_uk_updated)) + continue; + } + if (trigger_action == TRIGGER_DDL && ddl_action) { // Skip triggers not matching our action diff --git a/src/jrd/idx.cpp b/src/jrd/idx.cpp index c028f1c27f2..04749f6e8f6 100644 --- a/src/jrd/idx.cpp +++ b/src/jrd/idx.cpp @@ -1283,6 +1283,8 @@ void IDX_modify(thread_db* tdbb, RelationPages* relPages = org_rpb->rpb_relation->getPages(tdbb); WIN window(relPages->rel_pg_space_id, -1); + new_rpb->rpb_runtime_flags &= ~RPB_uk_updated; + while (BTR_next_index(tdbb, org_rpb->rpb_relation, transaction, &idx, &window)) { IndexErrorContext context(new_rpb->rpb_relation, &idx); @@ -1346,6 +1348,9 @@ void IDX_modify(thread_db* tdbb, { context.raise(tdbb, error_code, new_rpb->rpb_record); } + + if (idx.idx_flags & (idx_primary | idx_unique)) + new_rpb->rpb_runtime_flags |= RPB_uk_updated; } } diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h index 973d26ace38..cfeb0c4d20e 100644 --- a/src/jrd/jrd.h +++ b/src/jrd/jrd.h @@ -137,19 +137,19 @@ class Trigger public: Firebird::HalfStaticArray blr; // BLR code Firebird::HalfStaticArray debugInfo; // Debug info - Statement* statement; // Compiled statement + Statement* statement; // Compiled statement bool releaseInProgress; - bool sysTrigger; + SSHORT sysTrigger; // See fb_sysflag in constants.h FB_UINT64 type; // Trigger type USHORT flags; // Flags as they are in RDB$TRIGGERS table jrd_rel* relation; // Trigger parent relation - MetaName name; // Trigger name - MetaName engine; // External engine name + MetaName name; // Trigger name + MetaName engine; // External engine name Firebird::string entryPoint; // External trigger entrypoint Firebird::string extBody; // External trigger body ExtEngineManager::Trigger* extTrigger; // External trigger Nullable ssDefiner; - MetaName owner; // Owner for SQL SECURITY + MetaName owner; // Owner for SQL SECURITY bool isActive() const; diff --git a/src/jrd/met.epp b/src/jrd/met.epp index 3a6a725da20..0184eac6e3f 100644 --- a/src/jrd/met.epp +++ b/src/jrd/met.epp @@ -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, SSHORT, USHORT, const MetaName&, const string&, const bid*, Nullable 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, SSHORT, USHORT, const MetaName&, const string&, const bid*, Nullable ssDefiner); static void scan_partners(thread_db*, jrd_rel*); static bool verify_TRG_ignore_perm(thread_db*, const MetaName&); @@ -2049,7 +2049,7 @@ void MET_load_trigger(thread_db* tdbb, triggers, TRG.RDB$TRIGGER_NAME, TRG.RDB$TRIGGER_TYPE, - (bool) TRG.RDB$SYSTEM_FLAG, + TRG.RDB$SYSTEM_FLAG, trig_flags, engine, entryPoint, @@ -2070,7 +2070,7 @@ void MET_load_trigger(thread_db* tdbb, triggers + trigger_action, TRG.RDB$TRIGGER_NAME, (UCHAR) trigger_action, - (bool) TRG.RDB$SYSTEM_FLAG, + TRG.RDB$SYSTEM_FLAG, trig_flags, engine, entryPoint, @@ -3382,7 +3382,7 @@ void MET_parse_sys_trigger(thread_db* tdbb, jrd_rel* relation) 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, "", + save_trigger_data(tdbb, ptr, relation, statement, NULL, NULL, NULL, type, TRG.RDB$SYSTEM_FLAG, 0, "", "", NULL, Nullable()); } } @@ -4744,7 +4744,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, + SSHORT sys_trigger, USHORT flags, const MetaName& engine, const string& entryPoint, const bid* body, Nullable ssDefiner) { @@ -5126,7 +5126,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, + SSHORT sys_trigger, USHORT flags, const MetaName& engine, const string& entryPoint, const bid* body, Nullable ssDefiner) { diff --git a/src/jrd/req.h b/src/jrd/req.h index 23f6303d1f1..e8f800a7f9e 100644 --- a/src/jrd/req.h +++ b/src/jrd/req.h @@ -136,9 +136,10 @@ const USHORT RPB_undo_data = 0x02; // data got from undo log const USHORT RPB_undo_read = 0x04; // read was performed using the undo log const USHORT RPB_undo_deleted = 0x08; // read was performed using the undo log, primary version is deleted const USHORT RPB_just_deleted = 0x10; // record was just deleted by us +const USHORT RPB_uk_updated = 0x20; // set by IDX_modify if it insert key into any primary or unique index const USHORT RPB_UNDO_FLAGS = (RPB_undo_data | RPB_undo_read | RPB_undo_deleted); -const USHORT RPB_CLEAR_FLAGS = (RPB_UNDO_FLAGS | RPB_just_deleted); +const USHORT RPB_CLEAR_FLAGS = (RPB_UNDO_FLAGS | RPB_just_deleted | RPB_uk_updated); // List of active blobs controlled by request