Skip to content

Commit 6f8a8ed

Browse files
MDEV-31180: MyISAMMRG Crash on UPDATE of an updateable VIEW
Attach the children of a MERGE table once per statement, and keep the value of pos_in_table_list for a MERGE table on subsequent executions of a prepared statement.
1 parent 6d35ae3 commit 6f8a8ed

3 files changed

Lines changed: 92 additions & 9 deletions

File tree

‎mysql-test/suite/merge/merge.result‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4001,6 +4001,43 @@ SET SQL_SAFE_UPDATES=1;
40014001
UPDATE t1 STRAIGHT_JOIN t2 SET a = 89 WHERE 9 IN (SELECT c FROM t3 WHERE c IN (SELECT MAX(d) FROM t4));
40024002
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
40034003
DROP TABLE t1, t2, t3, t4;
4004+
SET SQL_SAFE_UPDATES=DEFAULT;
40044005
#
40054006
# End of 10.11 tests
40064007
#
4008+
#
4009+
# MDEV-31180: MyISAMMRG Crash on UPDATE of an updateable VIEW
4010+
#
4011+
CREATE TABLE t (f INT) ENGINE=MyISAM;
4012+
INSERT INTO t VALUES (1),(2);
4013+
CREATE TABLE tm (f INT) ENGINE=MERGE UNION (t) INSERT_METHOD=FIRST;
4014+
CREATE VIEW v AS SELECT f FROM tm;
4015+
UPDATE v SET f = 3;
4016+
SELECT * FROM v;
4017+
f
4018+
3
4019+
3
4020+
SELECT * FROM tm;
4021+
f
4022+
3
4023+
3
4024+
DROP VIEW v;
4025+
DROP TABLE tm, t;
4026+
CREATE TABLE t (f INT) ENGINE=MyISAM;
4027+
INSERT INTO t VALUES (1),(2);
4028+
CREATE TABLE tm (f INT) ENGINE=MERGE UNION (t) INSERT_METHOD=FIRST;
4029+
CREATE VIEW v AS SELECT f FROM tm;
4030+
PREPARE s FROM 'UPDATE v SET f = 3';
4031+
EXECUTE s;
4032+
EXECUTE s;
4033+
SELECT * FROM v;
4034+
f
4035+
3
4036+
3
4037+
SELECT * FROM tm;
4038+
f
4039+
3
4040+
3
4041+
DROP VIEW v;
4042+
DROP TABLE tm, t;
4043+
# End of 11.4 tests

‎mysql-test/suite/merge/merge.test‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2945,7 +2945,38 @@ SET SQL_SAFE_UPDATES=1;
29452945
UPDATE t1 STRAIGHT_JOIN t2 SET a = 89 WHERE 9 IN (SELECT c FROM t3 WHERE c IN (SELECT MAX(d) FROM t4));
29462946

29472947
DROP TABLE t1, t2, t3, t4;
2948+
SET SQL_SAFE_UPDATES=DEFAULT;
29482949

29492950
--echo #
29502951
--echo # End of 10.11 tests
29512952
--echo #
2953+
2954+
--echo #
2955+
--echo # MDEV-31180: MyISAMMRG Crash on UPDATE of an updateable VIEW
2956+
--echo #
2957+
# Simple UPDATE through a VIEW with the MERGE engine.
2958+
CREATE TABLE t (f INT) ENGINE=MyISAM;
2959+
INSERT INTO t VALUES (1),(2);
2960+
CREATE TABLE tm (f INT) ENGINE=MERGE UNION (t) INSERT_METHOD=FIRST;
2961+
CREATE VIEW v AS SELECT f FROM tm;
2962+
UPDATE v SET f = 3; # crashed here
2963+
SELECT * FROM v;
2964+
SELECT * FROM tm;
2965+
DROP VIEW v;
2966+
DROP TABLE tm, t;
2967+
2968+
# Prepared statement UPDATE through a VIEW with the MERGE engine, multiple
2969+
# executions.
2970+
CREATE TABLE t (f INT) ENGINE=MyISAM;
2971+
INSERT INTO t VALUES (1),(2);
2972+
CREATE TABLE tm (f INT) ENGINE=MERGE UNION (t) INSERT_METHOD=FIRST;
2973+
CREATE VIEW v AS SELECT f FROM tm;
2974+
PREPARE s FROM 'UPDATE v SET f = 3';
2975+
EXECUTE s; # no problem
2976+
EXECUTE s; # Asserted on pos_in_table_list->next_global == children_l, ha_myisammrg.cc:864
2977+
SELECT * FROM v;
2978+
SELECT * FROM tm;
2979+
DROP VIEW v;
2980+
DROP TABLE tm, t;
2981+
2982+
--echo # End of 11.4 tests

‎sql/sql_base.cc‎

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4897,10 +4897,10 @@ bool open_tables(THD *thd, const DDL_options_st &options,
48974897
}
48984898

48994899
/*
4900-
After successful open of all tables, including MERGE parents and
4901-
children, attach the children to their parents. At end of statement,
4902-
the children are detached. Attaching and detaching are always done,
4903-
even under LOCK TABLES.
4900+
After successfully opening the tables, including MERGE parents and
4901+
children, attach the children to their parents (unless they are already
4902+
attached). At the end of statement, the children are detached. Attaching
4903+
and detaching are always attempted, even under LOCK TABLES.
49044904
49054905
We also convert all TL_WRITE_DEFAULT and TL_READ_DEFAULT locks to
49064906
appropriate "real" lock types to be used for locking and to be passed
@@ -4916,7 +4916,8 @@ bool open_tables(THD *thd, const DDL_options_st &options,
49164916
if (!tbl)
49174917
continue;
49184918

4919-
if (tbl->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE)
4919+
if (tbl->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE &&
4920+
!tbl->file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN))
49204921
{
49214922
/* MERGE tables need to access parent and child TABLE_LISTs. */
49224923
if (tbl->file->extra(HA_EXTRA_ATTACH_CHILDREN))
@@ -8545,10 +8546,24 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
85458546
}
85468547
else
85478548
{
8548-
table_list->table->tablenr= table_list->tablenr_exec;
8549-
table_list->table->map= table_list->map_exec;
8550-
table_list->table->maybe_null= table_list->maybe_null_exec;
8551-
table_list->table->pos_in_table_list= table_list;
8549+
TABLE *tbl= table_list->table;
8550+
tbl->tablenr= table_list->tablenr_exec;
8551+
tbl->map= table_list->map_exec;
8552+
tbl->maybe_null= table_list->maybe_null_exec;
8553+
/*
8554+
If this is a MyISAM MERGE table then don't overwrite
8555+
pos_in_table_list on subsequent execution of a prepared statement
8556+
where that statement references a MyISAM MERGE table. On the first
8557+
execution, the pos_in_table_list is set to a value from 'leaves'.
8558+
But on subsequent executions, that value was blindly overwritten from
8559+
'leaf_tables_exec'. Most of the time that's safe, but not for the
8560+
MyISAM MERGE. The MyISAM MERGE engine relies on this value being
8561+
stable between executions so that it can find the children spliced in
8562+
behind the parent (the merged children).
8563+
*/
8564+
if (!(tbl->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE) ||
8565+
!tbl->pos_in_table_list)
8566+
tbl->pos_in_table_list= table_list;
85528567
if (table_list->process_index_hints(table_list->table))
85538568
DBUG_RETURN(1);
85548569
}

0 commit comments

Comments
 (0)