@@ -370,6 +370,32 @@ row_ins_cascade_ancestor_updates_table(
370
370
return (FALSE);
371
371
}
372
372
373
+ /*************************************************************************
374
+ Returns the number of ancestor UPDATE or DELETE nodes of a
375
+ cascaded update/delete node. */
376
+ static
377
+ ulint
378
+ row_ins_cascade_n_ancestors (
379
+ /*========================*/
380
+ /* out: number of ancestors */
381
+ que_node_t * node ) /* in: node in a query graph */
382
+ {
383
+ que_node_t * parent ;
384
+ ulint n_ancestors = 0 ;
385
+
386
+ parent = que_node_get_parent (node );
387
+
388
+ while (que_node_get_type (parent ) == QUE_NODE_UPDATE ) {
389
+ n_ancestors ++ ;
390
+
391
+ parent = que_node_get_parent (parent );
392
+
393
+ ut_a (parent );
394
+ }
395
+
396
+ return (n_ancestors );
397
+ }
398
+
373
399
/**********************************************************************
374
400
Calculates the update vector node->cascade->update for a child table in
375
401
a cascaded update. */
@@ -615,6 +641,34 @@ row_ins_foreign_report_add_err(
615
641
mutex_exit (& dict_foreign_err_mutex );
616
642
}
617
643
644
+ /*************************************************************************
645
+ Invalidate the query cache for the given table. */
646
+ static
647
+ void
648
+ row_ins_invalidate_query_cache (
649
+ /*===========================*/
650
+ que_thr_t * thr , /* in: query thread whose run_node
651
+ is an update node */
652
+ const char * name ) /* in: table name prefixed with
653
+ database name and a '/' character */
654
+ {
655
+ char * buf ;
656
+ char * ptr ;
657
+ ulint len = strlen (name ) + 1 ;
658
+
659
+ buf = mem_strdupl (name , len );
660
+
661
+ ptr = strchr (buf , '/' );
662
+ ut_a (ptr );
663
+ * ptr = '\0' ;
664
+
665
+ /* We call a function in ha_innodb.cc */
666
+ #ifndef UNIV_HOTBACKUP
667
+ innobase_invalidate_query_cache (thr_get_trx (thr ), buf , len );
668
+ #endif
669
+ mem_free (buf );
670
+ }
671
+
618
672
/*************************************************************************
619
673
Perform referential actions or checks when a parent row is deleted or updated
620
674
and the constraint had an ON DELETE or ON UPDATE condition which was not
@@ -650,26 +704,14 @@ row_ins_foreign_check_on_constraint(
650
704
ulint n_to_update ;
651
705
ulint err ;
652
706
ulint i ;
653
- char * ptr ;
654
- char table_name_buf [1000 ];
655
707
656
708
ut_a (thr && foreign && pcur && mtr );
657
709
658
710
/* Since we are going to delete or update a row, we have to invalidate
659
711
the MySQL query cache for table */
660
712
661
- ut_a (ut_strlen (table -> name ) < 998 );
662
- strcpy (table_name_buf , table -> name );
713
+ row_ins_invalidate_query_cache (thr , table -> name );
663
714
664
- ptr = strchr (table_name_buf , '/' );
665
- ut_a (ptr );
666
- * ptr = '\0' ;
667
-
668
- /* We call a function in ha_innodb.cc */
669
- #ifndef UNIV_HOTBACKUP
670
- innobase_invalidate_query_cache (thr_get_trx (thr ), table_name_buf ,
671
- ut_strlen (table -> name ) + 1 );
672
- #endif
673
715
node = thr -> run_node ;
674
716
675
717
if (node -> is_delete && 0 == (foreign -> type &
@@ -756,6 +798,16 @@ row_ins_foreign_check_on_constraint(
756
798
goto nonstandard_exit_func ;
757
799
}
758
800
801
+ if (row_ins_cascade_n_ancestors (cascade ) >= 15 ) {
802
+ err = DB_ROW_IS_REFERENCED ;
803
+
804
+ row_ins_foreign_report_err (
805
+ (char * )"Trying a too deep cascaded delete or update\n" ,
806
+ thr , foreign , btr_pcur_get_rec (pcur ), entry );
807
+
808
+ goto nonstandard_exit_func ;
809
+ }
810
+
759
811
index = btr_pcur_get_btr_cur (pcur )-> index ;
760
812
761
813
ut_a (index == foreign -> foreign_index );
0 commit comments