@@ -4802,6 +4802,25 @@ handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
4802
4802
}
4803
4803
4804
4804
4805
+ /*
4806
+ @note this can be changed to use a hash, instead of scanning the linked
4807
+ list, if the performance of this function will ever become an issue
4808
+ */
4809
+ static bool table_already_fk_prelocked (TABLE_LIST *tl, LEX_STRING *db,
4810
+ LEX_STRING *table, thr_lock_type lock_type)
4811
+ {
4812
+ for (; tl; tl= tl->next_global )
4813
+ {
4814
+ if (tl->lock_type >= lock_type &&
4815
+ tl->prelocking_placeholder == TABLE_LIST::FK &&
4816
+ strcmp (tl->db , db->str ) == 0 &&
4817
+ strcmp (tl->table_name , table->str ) == 0 )
4818
+ return true ;
4819
+ }
4820
+ return false ;
4821
+ }
4822
+
4823
+
4805
4824
/* *
4806
4825
Defines how prelocking algorithm for DML statements should handle table list
4807
4826
elements:
@@ -4841,6 +4860,52 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
4841
4860
add_tables_and_routines_for_triggers (thd, prelocking_ctx, table_list))
4842
4861
return TRUE ;
4843
4862
}
4863
+
4864
+ if (table_list->table ->file ->referenced_by_foreign_key ())
4865
+ {
4866
+ List <FOREIGN_KEY_INFO> fk_list;
4867
+ List_iterator<FOREIGN_KEY_INFO> fk_list_it (fk_list);
4868
+ FOREIGN_KEY_INFO *fk;
4869
+ Query_arena *arena, backup;
4870
+
4871
+ arena= thd->activate_stmt_arena_if_needed (&backup);
4872
+
4873
+ table_list->table ->file ->get_parent_foreign_key_list (thd, &fk_list);
4874
+ if (thd->is_error ())
4875
+ {
4876
+ if (arena)
4877
+ thd->restore_active_arena (arena, &backup);
4878
+ return TRUE ;
4879
+ }
4880
+
4881
+ *need_prelocking= TRUE ;
4882
+
4883
+ while ((fk= fk_list_it++))
4884
+ {
4885
+ // FK_OPTION_RESTRICT and FK_OPTION_NO_ACTION only need read access
4886
+ static bool can_write[]= { true , false , true , true , false , true };
4887
+ uint8 op= table_list->trg_event_map ;
4888
+ thr_lock_type lock_type;
4889
+
4890
+ if ((op & (1 << TRG_EVENT_DELETE) && can_write[fk->delete_method ])
4891
+ || (op & (1 << TRG_EVENT_UPDATE) && can_write[fk->update_method ]))
4892
+ lock_type= TL_WRITE_ALLOW_WRITE;
4893
+ else
4894
+ lock_type= TL_READ;
4895
+
4896
+ if (table_already_fk_prelocked (table_list, fk->foreign_db ,
4897
+ fk->foreign_table , lock_type))
4898
+ continue ;
4899
+
4900
+ TABLE_LIST *tl= (TABLE_LIST *) thd->alloc (sizeof (TABLE_LIST));
4901
+ tl->init_one_table_for_prelocking (fk->foreign_db ->str , fk->foreign_db ->length ,
4902
+ fk->foreign_table ->str , fk->foreign_table ->length ,
4903
+ NULL , lock_type, false , table_list->belong_to_view ,
4904
+ op, &prelocking_ctx->query_tables_last );
4905
+ }
4906
+ if (arena)
4907
+ thd->restore_active_arena (arena, &backup);
4908
+ }
4844
4909
}
4845
4910
4846
4911
return FALSE ;
0 commit comments