Below is the list of changes that have just been committed into a local
5.1 repository of istruewing. When istruewing does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-11-14 19:37:36+01:00, istruewing@stripped +16 -0
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Not to be pushed as is.
Post-review fixes.
Intermediate patch for review purpose.
Still open issue: Move temporary detach to
mark_temp_tables_as_free_for_reuse(). This requires a current
repository.
Not contained in this patch: Reverted creation of new test case
rpl_merge. It was for CREATE...SELECT only.
mysql-test/r/create.result@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +1 -1
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Fixed test result.
mysql-test/r/delayed.result@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +0 -5
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Moved test result from here to merge.result.
mysql-test/r/merge.result@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +226 -80
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Fixed/added test result.
mysql-test/t/create.test@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +1 -1
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Fixed error number.
mysql-test/t/delayed.test@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +0 -8
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Moved test from here to merge.test.
mysql-test/t/merge.test@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +164 -49
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Fixed changes resulting from disabled CREATE...SELECT.
Added more tests.
Integrated test moved from delayed.test to here.
sql/slave.cc@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +8 -2
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Reverted to open_ltable().
sql/sql_base.cc@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +192 -109
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Moved multi-line conditions into a member function of TABLE.
Moved MERGE part of unlink_open_table() to new function
unlink_open_merge().
Moved MERGE part of reopen_tables() to new function
reattach_merge().
Prevented from infinite recursion when MERGE tables try to
include themselves in a ring.
Simplified the compatibility check in fix_merge_after_open().
sql/sql_insert.cc@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +0 -86
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Reverted changes from create_table_from_items().
sql/sql_parse.cc@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +23 -15
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Reverted changes from check_merge_table_access(). But kept it static.
Reverted to open_ltable() in mysql_table_dump().
Disabled use of CREATE...SELECT for MERGE tables.
sql/sql_table.cc@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +18 -19
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Changed error reporting to asserting in prepare_for_restore()
and prepare_for_repair().
Disabled change of child list under LOCK TABLES.
sql/table.cc@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +19 -0
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Added member function TABLE::is_children_attached().
sql/table.h@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +1 -0
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Added member function TABLE::is_children_attached().
storage/myisam/ha_myisam.cc@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +0 -22
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Reverted new function myisam_engine_handle() to not implemented.
storage/myisam/ha_myisam.h@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +4 -4
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Reverted new function myisam_engine_handle() to not implemented.
Added new member function MI_INFO::file_ptr().
storage/myisammrg/ha_myisammrg.cc@stripped, 2007-11-14 19:37:34+01:00, istruewing@stripped +11 -1
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Changed from myisam_engine_handle() to file_ptr().
diff -Nrup a/mysql-test/r/create.result b/mysql-test/r/create.result
--- a/mysql-test/r/create.result 2007-10-08 00:02:43 +02:00
+++ b/mysql-test/r/create.result 2007-11-14 19:37:34 +01:00
@@ -594,7 +594,7 @@ create table t1 (a int);
create table t1 select * from t1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
create table t2 union = (t1) select * from t1;
-ERROR HY000: You can't specify target table 't1' for update in FROM clause
+ERROR HY000: 'test.t2' is not BASE TABLE
flush tables with read lock;
unlock tables;
drop table t1;
diff -Nrup a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
--- a/mysql-test/r/delayed.result 2007-09-10 11:37:48 +02:00
+++ b/mysql-test/r/delayed.result 2007-11-14 19:37:34 +01:00
@@ -250,11 +250,6 @@ SELECT HEX(a) FROM t1;
HEX(a)
1
DROP TABLE t1;
-CREATE TABLE t1(c1 INT) ENGINE=MyISAM;
-CREATE TABLE t2(c1 INT) ENGINE=MERGE UNION=(t1);
-INSERT DELAYED INTO t2 VALUES(1);
-ERROR HY000: Table storage engine for 't2' doesn't have this option
-DROP TABLE t1, t2;
DROP TABLE IF EXISTS t1,t2;
SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
CREATE TABLE `t1` (
diff -Nrup a/mysql-test/r/merge.result b/mysql-test/r/merge.result
--- a/mysql-test/r/merge.result 2007-11-02 17:28:15 +01:00
+++ b/mysql-test/r/merge.result 2007-11-14 19:37:34 +01:00
@@ -615,6 +615,7 @@ create temporary table t3 (a int not nul
select * from t3;
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
drop table t3, t2, t1;
+# CREATE...SELECT is not implemented for MERGE tables.
CREATE TEMPORARY TABLE t1 (c1 INT NOT NULL);
CREATE TEMPORARY TABLE t2 (c1 INT NOT NULL);
CREATE TABLE t3 (c1 INT NOT NULL);
@@ -622,11 +623,13 @@ INSERT INTO t3 VALUES (3), (33);
LOCK TABLES t3 READ;
CREATE TEMPORARY TABLE t4 (c1 INT NOT NULL) ENGINE=MERGE UNION=(t1,t2)
INSERT_METHOD=LAST SELECT * FROM t3;
+ERROR HY000: 'test.t4' is not BASE TABLE
SELECT * FROM t4;
-c1
-3
-33
+ERROR HY000: Table 't4' was not locked with LOCK TABLES
UNLOCK TABLES;
+CREATE TEMPORARY TABLE t4 (c1 INT NOT NULL) ENGINE=MERGE UNION=(t1,t2)
+INSERT_METHOD=LAST;
+INSERT INTO t4 SELECT * FROM t3;
# Alter temporary MERGE table.
ALTER TABLE t4 UNION=(t1);
LOCK TABLES t4 WRITE;
@@ -693,11 +696,11 @@ create table t2 (a int);
insert into t1 values (0);
insert into t2 values (1);
create table t3 engine=merge union=(t1, t2) select * from t1;
-ERROR HY000: You can't specify target table 't1' for update in FROM clause
+ERROR HY000: 'test.t3' is not BASE TABLE
create table t3 engine=merge union=(t1, t2) select * from t2;
-ERROR HY000: You can't specify target table 't2' for update in FROM clause
+ERROR HY000: 'test.t3' is not BASE TABLE
create table t3 engine=merge union=(t1, t2) select (select max(a) from t2);
-ERROR HY000: You can't specify target table 't2' for update in FROM clause
+ERROR HY000: 'test.t3' is not BASE TABLE
drop table t1, t2;
create table t1 (
a double(14,4),
@@ -1058,71 +1061,31 @@ DROP TABLE t1;
# Extra tests for Bug#26379 - Combination of FLUSH TABLE and
# REPAIR TABLE corrupts a MERGE table
#
-# CREATE ... SELECT
+# CREATE ... SELECT is disabled for MERGE tables.
#
-CREATE TABLE t1 (c1 INT);
-CREATE TABLE t2 (c1 INT);
-CREATE TABLE t3 (c1 INT);
+CREATE TABLE t1(c1 INT);
INSERT INTO t1 VALUES (1);
-INSERT INTO t2 VALUES (2);
-INSERT INTO t3 VALUES (3);
-# Show that LAST table is opened.
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
-INSERT_METHOD=LAST SELECT * FROM t3;
-SHOW CREATE TABLE t4;
-Table Create Table
-t4 CREATE TABLE `t4` (
- `c1` int(11) DEFAULT NULL
-) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
-SELECT * FROM t4 ORDER BY c1;
-c1
-1
-2
-3
-DROP TABLE t4;
-# Show that FIRST table is opened.
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
-INSERT_METHOD=FIRST SELECT * FROM t3;
-SHOW CREATE TABLE t4;
-Table Create Table
-t4 CREATE TABLE `t4` (
- `c1` int(11) DEFAULT NULL
-) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`)
-SELECT * FROM t4 ORDER BY c1;
-c1
-1
-2
-3
-3
-DROP TABLE t4;
-# Show that CREATE..SELECT is not possible under LOCK TABLES
-# for non-temporary tables.
-LOCK TABLES t1 WRITE, t2 WRITE, t3 READ;
-# Normal CREATE works.
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2);
-DROP TABLE t4;
-# CREATE...SELECT is rejected.
-CREATE TABLE t4 (c1 INT) SELECT * FROM t3;
-ERROR HY000: Table 't4' was not locked with LOCK TABLES
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
-INSERT_METHOD=LAST SELECT * FROM t3;
-ERROR HY000: Table 't4' was not locked with LOCK TABLES
-UNLOCK TABLES;
-# LOCK on parent table does not include children.
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2);
-LOCK TABLES t4 READ;
-SELECT * from t1, t4 ORDER BY c1;
-ERROR HY000: Table 't1' was not locked with LOCK TABLES
-# Show that dropping a locked MERGE table works.
-DROP TABLE t4;
-UNLOCK TABLES;
-DROP TABLE t3;
+CREATE TABLE t2 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
+CREATE TABLE t3 ENGINE=MRG_MYISAM INSERT_METHOD=LAST SELECT * FROM t2;
+ERROR HY000: Table 't3' is read only
+SHOW CREATE TABLE t3;
+ERROR 42S02: Table 'test.t3' doesn't exist
+CREATE TABLE t3 ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST
+SELECT * FROM t2;
+ERROR HY000: 'test.t3' is not BASE TABLE
+SHOW CREATE TABLE t3;
+ERROR 42S02: Table 'test.t3' doesn't exist
+DROP TABLE t1, t2;
#
# CREATE ... LIKE
#
# 1. Create like.
+CREATE TABLE t1 (c1 INT);
+CREATE TABLE t2 (c1 INT);
CREATE TABLE t3 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
INSERT_METHOD=LAST;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
INSERT INTO t3 VALUES (3);
CREATE TABLE t4 LIKE t3;
SHOW CREATE TABLE t4;
@@ -1175,8 +1138,6 @@ c1
1
2
3
-3
-3
RENAME TABLE t2 TO t5;
SELECT * FROM t3 ORDER BY c1;
ERROR 42S02: Table 'test.t2' doesn't exist
@@ -1186,8 +1147,6 @@ c1
1
2
3
-3
-3
#
# 3. Normal rename with locked tables.
LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE;
@@ -1196,8 +1155,6 @@ c1
1
2
3
-3
-3
RENAME TABLE t2 TO t5;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SELECT * FROM t3 ORDER BY c1;
@@ -1205,8 +1162,6 @@ c1
1
2
3
-3
-3
RENAME TABLE t5 TO t2;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SELECT * FROM t3 ORDER BY c1;
@@ -1214,8 +1169,6 @@ c1
1
2
3
-3
-3
UNLOCK TABLES;
#
# 4. Alter table rename.
@@ -1228,8 +1181,6 @@ c1
1
2
3
-3
-3
#
# 5. Alter table rename with locked tables.
LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE;
@@ -1245,7 +1196,43 @@ c1
1
2
3
+#
+# Rename parent.
+#
+# 1. Normal rename with locked tables.
+LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE;
+SELECT * FROM t3 ORDER BY c1;
+c1
+1
+2
+3
+RENAME TABLE t3 TO t5;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+SELECT * FROM t3 ORDER BY c1;
+c1
+1
+2
+3
+RENAME TABLE t5 TO t3;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+SELECT * FROM t3 ORDER BY c1;
+c1
+1
+2
3
+#
+# 5. Alter table rename with locked tables.
+ALTER TABLE t3 RENAME TO t5;
+SELECT * FROM t5 ORDER BY c1;
+ERROR HY000: Table 't5' was not locked with LOCK TABLES
+ALTER TABLE t5 RENAME TO t3;
+ERROR HY000: Table 't5' was not locked with LOCK TABLES
+UNLOCK TABLES;
+ALTER TABLE t5 RENAME TO t3;
+SELECT * FROM t3 ORDER BY c1;
+c1
+1
+2
3
DROP TABLE t1, t2, t3;
#
@@ -1277,16 +1264,69 @@ ERROR 42S02: Table 'test.t1' doesn't exi
UNLOCK TABLES;
DROP TABLE t2;
#
-# ALTER TABLE under LOCK TABLES. Grave change, table re-creation.
+# ALTER TABLE. Change child list.
#
CREATE TABLE t1 (c1 INT, INDEX(c1));
CREATE TABLE t2 (c1 INT, INDEX(c1));
CREATE TABLE t3 (c1 INT, INDEX(c1));
-CREATE TABLE t4 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1,t2,t3)
-INSERT_METHOD=LAST;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
INSERT INTO t3 VALUES (3);
+CREATE TABLE t4 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t3,t2)
+INSERT_METHOD=LAST;
+# Shrink child list.
+ALTER TABLE t4 UNION=(t3);
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c1` int(11) DEFAULT NULL,
+ KEY `c1` (`c1`)
+) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t3`)
+SELECT * FROM t4 ORDER BY c1;
+c1
+3
+# Extend child list.
+ALTER TABLE t4 UNION=(t3,t2);
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c1` int(11) DEFAULT NULL,
+ KEY `c1` (`c1`)
+) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t3`,`t2`)
+SELECT * FROM t4 ORDER BY c1;
+c1
+2
+3
+#
+# ALTER TABLE under LOCK TABLES. Change child list.
+#
+LOCK TABLES t4 WRITE, t3 WRITE, t2 WRITE;
+# Shrink child list.
+ALTER TABLE t4 UNION=(t3);
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# Extend child list within locked tables.
+ALTER TABLE t4 UNION=(t3,t2);
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# Extend child list beyond locked tables.
+ALTER TABLE t4 UNION=(t3,t2,t1);
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c1` int(11) DEFAULT NULL,
+ KEY `c1` (`c1`)
+) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t3`,`t2`)
+SELECT * FROM t4 ORDER BY c1;
+c1
+2
+3
+UNLOCK TABLES;
+DROP TABLE t4;
+#
+# ALTER TABLE under LOCK TABLES. Grave change, table re-creation.
+#
+CREATE TABLE t4 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1,t2,t3)
+INSERT_METHOD=LAST;
# Lock parent first and then children.
LOCK TABLES t4 WRITE, t3 WRITE, t2 WRITE, t1 WRITE;
ALTER TABLE t4 DROP INDEX c1, ADD UNIQUE INDEX (c1);
@@ -1458,6 +1498,8 @@ UNLOCK TABLES;
#
# Triggers
#
+# Trigger on parent
+DELETE FROM t4 WHERE c1 = 4;
CREATE TRIGGER t4_ai AFTER INSERT ON t4 FOR EACH ROW SET @a=1;
SET @a=0;
INSERT INTO t4 VALUES (4);
@@ -1471,7 +1513,7 @@ c1
3
4
DROP TRIGGER t4_ai;
-# Create trigger with LOCK
+# Trigger on parent under LOCK TABLES
LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE;
CREATE TRIGGER t4_ai AFTER INSERT ON t4 FOR EACH ROW SET @a=1;
SET @a=0;
@@ -1489,6 +1531,98 @@ c1
DROP TRIGGER t4_ai;
UNLOCK TABLES;
#
+# Trigger on child
+DELETE FROM t4 WHERE c1 = 4;
+CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW SET @a=1;
+SET @a=0;
+INSERT INTO t4 VALUES (4);
+SELECT @a;
+@a
+0
+INSERT INTO t3 VALUES (33);
+SELECT @a;
+@a
+1
+SELECT * FROM t4 ORDER BY c1;
+c1
+1
+2
+3
+4
+33
+DROP TRIGGER t3_ai;
+# Trigger on child under LOCK TABLES
+LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE;
+CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW SET @a=1;
+SET @a=0;
+INSERT INTO t4 VALUES (4);
+SELECT @a;
+@a
+0
+INSERT INTO t3 VALUES (33);
+SELECT @a;
+@a
+1
+SELECT * FROM t4 ORDER BY c1;
+c1
+1
+2
+3
+4
+4
+33
+33
+DELETE FROM t4 WHERE c1 = 33;
+DROP TRIGGER t3_ai;
+#
+# Trigger with table use on child
+DELETE FROM t4 WHERE c1 = 4;
+CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW INSERT INTO t2 VALUES(22);
+INSERT INTO t4 VALUES (4);
+SELECT * FROM t4 ORDER BY c1;
+c1
+1
+2
+3
+4
+INSERT INTO t3 VALUES (33);
+SELECT * FROM t4 ORDER BY c1;
+c1
+1
+2
+3
+4
+22
+33
+DELETE FROM t4 WHERE c1 = 22;
+DELETE FROM t4 WHERE c1 = 33;
+DROP TRIGGER t3_ai;
+# Trigger with table use on child under LOCK TABLES
+LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE;
+CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW INSERT INTO t2 VALUES(22);
+INSERT INTO t4 VALUES (4);
+SELECT * FROM t4 ORDER BY c1;
+c1
+1
+2
+3
+4
+4
+INSERT INTO t3 VALUES (33);
+SELECT * FROM t4 ORDER BY c1;
+c1
+1
+2
+3
+4
+4
+22
+33
+DROP TRIGGER t3_ai;
+DELETE FROM t4 WHERE c1 = 22;
+DELETE FROM t4 WHERE c1 = 33;
+UNLOCK TABLES;
+#
# Repair
#
REPAIR TABLE t4;
@@ -1585,7 +1719,7 @@ UNLOCK TABLES;
# Insert delayed
#
INSERT DELAYED INTO t4 VALUES(44);
-ERROR HY000: Table storage engine for 't4' doesn't have this option
+DELETE FROM t4 WHERE c1 = 44;
INSERT DELAYED INTO t3 VALUES(33);
SELECT * FROM t4 ORDER BY c1;
c1
@@ -1610,6 +1744,18 @@ c1
33
UNLOCK TABLES;
DROP TABLE t1, t2, t3, t4;
+#
+# Recursive inclusion of merge tables in their union clauses.
+#
+CREATE TABLE t1 (c1 INT, INDEX(c1));
+CREATE TABLE t2 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1)
+INSERT_METHOD=LAST;
+CREATE TABLE t3 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t2,t1)
+INSERT_METHOD=LAST;
+ALTER TABLE t2 UNION=(t3,t1);
+SELECT * FROM t2;
+ERROR HY000: Table 't3' is differently defined or of non-MyISAM type or doesn't exist
+DROP TABLE t1, t2, t3;
CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
CREATE TABLE t2 (c1 INT) ENGINE= MyISAM;
CREATE TABLE t3 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1, t2);
diff -Nrup a/mysql-test/t/create.test b/mysql-test/t/create.test
--- a/mysql-test/t/create.test 2007-09-28 23:25:42 +02:00
+++ b/mysql-test/t/create.test 2007-11-14 19:37:34 +01:00
@@ -483,7 +483,7 @@ drop table t1,t2;
create table t1 (a int);
--error 1093
create table t1 select * from t1;
---error 1093
+--error ER_WRONG_OBJECT
create table t2 union = (t1) select * from t1;
flush tables with read lock;
unlock tables;
diff -Nrup a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
--- a/mysql-test/t/delayed.test 2007-11-02 17:28:15 +01:00
+++ b/mysql-test/t/delayed.test 2007-11-14 19:37:34 +01:00
@@ -244,14 +244,6 @@ SELECT HEX(a) FROM t1;
DROP TABLE t1;
#
-# Bug#26464 - insert delayed + update + merge = corruption
-#
-CREATE TABLE t1(c1 INT) ENGINE=MyISAM;
-CREATE TABLE t2(c1 INT) ENGINE=MERGE UNION=(t1);
---error ER_ILLEGAL_HA
-INSERT DELAYED INTO t2 VALUES(1);
-DROP TABLE t1, t2;
-#
# Bug#27358 INSERT DELAYED does not honour SQL_MODE of the client
#
--disable_warnings
diff -Nrup a/mysql-test/t/merge.test b/mysql-test/t/merge.test
--- a/mysql-test/t/merge.test 2007-11-02 17:28:15 +01:00
+++ b/mysql-test/t/merge.test 2007-11-14 19:37:34 +01:00
@@ -256,16 +256,21 @@ create temporary table t3 (a int not nul
--error ER_WRONG_MRG_TABLE
select * from t3;
drop table t3, t2, t1;
-# Show CREATE...SELECT under LOCK TABLES:
+--echo # CREATE...SELECT is not implemented for MERGE tables.
CREATE TEMPORARY TABLE t1 (c1 INT NOT NULL);
CREATE TEMPORARY TABLE t2 (c1 INT NOT NULL);
CREATE TABLE t3 (c1 INT NOT NULL);
INSERT INTO t3 VALUES (3), (33);
LOCK TABLES t3 READ;
+--error ER_WRONG_OBJECT
CREATE TEMPORARY TABLE t4 (c1 INT NOT NULL) ENGINE=MERGE UNION=(t1,t2)
INSERT_METHOD=LAST SELECT * FROM t3;
+--error ER_TABLE_NOT_LOCKED
SELECT * FROM t4;
UNLOCK TABLES;
+CREATE TEMPORARY TABLE t4 (c1 INT NOT NULL) ENGINE=MERGE UNION=(t1,t2)
+ INSERT_METHOD=LAST;
+INSERT INTO t4 SELECT * FROM t3;
--echo # Alter temporary MERGE table.
ALTER TABLE t4 UNION=(t1);
LOCK TABLES t4 WRITE;
@@ -332,11 +337,11 @@ create table t1 (a int);
create table t2 (a int);
insert into t1 values (0);
insert into t2 values (1);
---error 1093
+--error ER_WRONG_OBJECT
create table t3 engine=merge union=(t1, t2) select * from t1;
---error 1093
+--error ER_WRONG_OBJECT
create table t3 engine=merge union=(t1, t2) select * from t2;
---error 1093
+--error ER_WRONG_OBJECT
create table t3 engine=merge union=(t1, t2) select (select max(a) from t2);
drop table t1, t2;
@@ -770,58 +775,38 @@ DROP TABLE t1;
# Cleanup
disconnect con1;
disconnect con2;
+#
--echo #
--echo # Extra tests for Bug#26379 - Combination of FLUSH TABLE and
--echo # REPAIR TABLE corrupts a MERGE table
+#
--echo #
---echo # CREATE ... SELECT
+--echo # CREATE ... SELECT is disabled for MERGE tables.
--echo #
-CREATE TABLE t1 (c1 INT);
-CREATE TABLE t2 (c1 INT);
-CREATE TABLE t3 (c1 INT);
+CREATE TABLE t1(c1 INT);
INSERT INTO t1 VALUES (1);
-INSERT INTO t2 VALUES (2);
-INSERT INTO t3 VALUES (3);
---echo # Show that LAST table is opened.
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
- INSERT_METHOD=LAST SELECT * FROM t3;
-SHOW CREATE TABLE t4;
-SELECT * FROM t4 ORDER BY c1;
-DROP TABLE t4;
---echo # Show that FIRST table is opened.
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
- INSERT_METHOD=FIRST SELECT * FROM t3;
-SHOW CREATE TABLE t4;
-SELECT * FROM t4 ORDER BY c1;
-DROP TABLE t4;
---echo # Show that CREATE..SELECT is not possible under LOCK TABLES
---echo # for non-temporary tables.
-LOCK TABLES t1 WRITE, t2 WRITE, t3 READ;
---echo # Normal CREATE works.
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2);
-DROP TABLE t4;
---echo # CREATE...SELECT is rejected.
---error ER_TABLE_NOT_LOCKED
-CREATE TABLE t4 (c1 INT) SELECT * FROM t3;
---error ER_TABLE_NOT_LOCKED
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
- INSERT_METHOD=LAST SELECT * FROM t3;
-UNLOCK TABLES;
---echo # LOCK on parent table does not include children.
-CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2);
-LOCK TABLES t4 READ;
---error ER_TABLE_NOT_LOCKED
-SELECT * from t1, t4 ORDER BY c1;
---echo # Show that dropping a locked MERGE table works.
-DROP TABLE t4;
-UNLOCK TABLES;
-DROP TABLE t3;
+CREATE TABLE t2 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
+--error ER_OPEN_AS_READONLY
+CREATE TABLE t3 ENGINE=MRG_MYISAM INSERT_METHOD=LAST SELECT * FROM t2;
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE t3;
+--error ER_WRONG_OBJECT
+CREATE TABLE t3 ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST
+ SELECT * FROM t2;
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE t3;
+DROP TABLE t1, t2;
+#
--echo #
--echo # CREATE ... LIKE
--echo #
--echo # 1. Create like.
+CREATE TABLE t1 (c1 INT);
+CREATE TABLE t2 (c1 INT);
CREATE TABLE t3 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2)
INSERT_METHOD=LAST;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
INSERT INTO t3 VALUES (3);
CREATE TABLE t4 LIKE t3;
SHOW CREATE TABLE t4;
@@ -841,6 +826,7 @@ SHOW CREATE TABLE t4;
--error ER_OPEN_AS_READONLY
INSERT INTO t4 VALUES (4);
DROP TABLE t4;
+#
--echo #
--echo # Rename child.
--echo #
@@ -890,7 +876,31 @@ ALTER TABLE t5 RENAME TO t2;
UNLOCK TABLES;
ALTER TABLE t5 RENAME TO t2;
SELECT * FROM t3 ORDER BY c1;
+#
+--echo #
+--echo # Rename parent.
+--echo #
+--echo # 1. Normal rename with locked tables.
+LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE;
+SELECT * FROM t3 ORDER BY c1;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+RENAME TABLE t3 TO t5;
+SELECT * FROM t3 ORDER BY c1;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+RENAME TABLE t5 TO t3;
+SELECT * FROM t3 ORDER BY c1;
+--echo #
+--echo # 5. Alter table rename with locked tables.
+ALTER TABLE t3 RENAME TO t5;
+--error ER_TABLE_NOT_LOCKED
+SELECT * FROM t5 ORDER BY c1;
+--error ER_TABLE_NOT_LOCKED
+ALTER TABLE t5 RENAME TO t3;
+UNLOCK TABLES;
+ALTER TABLE t5 RENAME TO t3;
+SELECT * FROM t3 ORDER BY c1;
DROP TABLE t1, t2, t3;
+#
--echo #
--echo # Drop locked tables.
--echo #
@@ -917,17 +927,50 @@ SELECT * FROM t2;
SELECT * FROM t1;
UNLOCK TABLES;
DROP TABLE t2;
+#
--echo #
---echo # ALTER TABLE under LOCK TABLES. Grave change, table re-creation.
+--echo # ALTER TABLE. Change child list.
--echo #
CREATE TABLE t1 (c1 INT, INDEX(c1));
CREATE TABLE t2 (c1 INT, INDEX(c1));
CREATE TABLE t3 (c1 INT, INDEX(c1));
-CREATE TABLE t4 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1,t2,t3)
- INSERT_METHOD=LAST;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
INSERT INTO t3 VALUES (3);
+CREATE TABLE t4 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t3,t2)
+ INSERT_METHOD=LAST;
+--echo # Shrink child list.
+ALTER TABLE t4 UNION=(t3);
+SHOW CREATE TABLE t4;
+SELECT * FROM t4 ORDER BY c1;
+--echo # Extend child list.
+ALTER TABLE t4 UNION=(t3,t2);
+SHOW CREATE TABLE t4;
+SELECT * FROM t4 ORDER BY c1;
+#
+--echo #
+--echo # ALTER TABLE under LOCK TABLES. Change child list.
+--echo #
+LOCK TABLES t4 WRITE, t3 WRITE, t2 WRITE;
+--echo # Shrink child list.
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+ALTER TABLE t4 UNION=(t3);
+--echo # Extend child list within locked tables.
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+ALTER TABLE t4 UNION=(t3,t2);
+--echo # Extend child list beyond locked tables.
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+ALTER TABLE t4 UNION=(t3,t2,t1);
+SHOW CREATE TABLE t4;
+SELECT * FROM t4 ORDER BY c1;
+UNLOCK TABLES;
+DROP TABLE t4;
+#
+--echo #
+--echo # ALTER TABLE under LOCK TABLES. Grave change, table re-creation.
+--echo #
+CREATE TABLE t4 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1,t2,t3)
+ INSERT_METHOD=LAST;
--echo # Lock parent first and then children.
LOCK TABLES t4 WRITE, t3 WRITE, t2 WRITE, t1 WRITE;
ALTER TABLE t4 DROP INDEX c1, ADD UNIQUE INDEX (c1);
@@ -950,6 +993,7 @@ ALTER TABLE t2 DROP INDEX c1, ADD UNIQUE
SELECT * FROM t4 ORDER BY c1;
UNLOCK TABLES;
DROP TABLE t1, t2, t3, t4;
+#
--echo #
--echo # ALTER TABLE under LOCK TABLES. Simple change, no re-creation.
--echo #
@@ -982,6 +1026,7 @@ SELECT * FROM t4 ORDER BY c1;
ALTER TABLE t2 ALTER COLUMN c1 SET DEFAULT 22;
SELECT * FROM t4 ORDER BY c1;
UNLOCK TABLES;
+#
--echo #
--echo # FLUSH TABLE under LOCK TABLES.
--echo #
@@ -1012,16 +1057,19 @@ SELECT * FROM t4 ORDER BY c1;
FLUSH TABLES;
SELECT * FROM t4 ORDER BY c1;
UNLOCK TABLES;
+#
--echo #
--echo # Triggers
--echo #
+--echo # Trigger on parent
+DELETE FROM t4 WHERE c1 = 4;
CREATE TRIGGER t4_ai AFTER INSERT ON t4 FOR EACH ROW SET @a=1;
SET @a=0;
INSERT INTO t4 VALUES (4);
SELECT @a;
SELECT * FROM t4 ORDER BY c1;
DROP TRIGGER t4_ai;
---echo # Create trigger with LOCK
+--echo # Trigger on parent under LOCK TABLES
LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE;
CREATE TRIGGER t4_ai AFTER INSERT ON t4 FOR EACH ROW SET @a=1;
SET @a=0;
@@ -1031,6 +1079,51 @@ SELECT * FROM t4 ORDER BY c1;
DROP TRIGGER t4_ai;
UNLOCK TABLES;
--echo #
+--echo # Trigger on child
+DELETE FROM t4 WHERE c1 = 4;
+CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW SET @a=1;
+SET @a=0;
+INSERT INTO t4 VALUES (4);
+SELECT @a;
+INSERT INTO t3 VALUES (33);
+SELECT @a;
+SELECT * FROM t4 ORDER BY c1;
+DROP TRIGGER t3_ai;
+--echo # Trigger on child under LOCK TABLES
+LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE;
+CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW SET @a=1;
+SET @a=0;
+INSERT INTO t4 VALUES (4);
+SELECT @a;
+INSERT INTO t3 VALUES (33);
+SELECT @a;
+SELECT * FROM t4 ORDER BY c1;
+DELETE FROM t4 WHERE c1 = 33;
+DROP TRIGGER t3_ai;
+--echo #
+--echo # Trigger with table use on child
+DELETE FROM t4 WHERE c1 = 4;
+CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW INSERT INTO t2 VALUES(22);
+INSERT INTO t4 VALUES (4);
+SELECT * FROM t4 ORDER BY c1;
+INSERT INTO t3 VALUES (33);
+SELECT * FROM t4 ORDER BY c1;
+DELETE FROM t4 WHERE c1 = 22;
+DELETE FROM t4 WHERE c1 = 33;
+DROP TRIGGER t3_ai;
+--echo # Trigger with table use on child under LOCK TABLES
+LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE;
+CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW INSERT INTO t2 VALUES(22);
+INSERT INTO t4 VALUES (4);
+SELECT * FROM t4 ORDER BY c1;
+INSERT INTO t3 VALUES (33);
+SELECT * FROM t4 ORDER BY c1;
+DROP TRIGGER t3_ai;
+DELETE FROM t4 WHERE c1 = 22;
+DELETE FROM t4 WHERE c1 = 33;
+UNLOCK TABLES;
+#
+--echo #
--echo # Repair
--echo #
REPAIR TABLE t4;
@@ -1041,6 +1134,7 @@ REPAIR TABLE t4;
REPAIR TABLE t2;
SELECT * FROM t4 ORDER BY c1;
UNLOCK TABLES;
+#
--echo #
--echo # Optimize
--echo #
@@ -1052,6 +1146,7 @@ OPTIMIZE TABLE t4;
OPTIMIZE TABLE t2;
SELECT * FROM t4 ORDER BY c1;
UNLOCK TABLES;
+#
--echo #
--echo # Checksum
--echo #
@@ -1063,11 +1158,18 @@ CHECKSUM TABLE t4;
CHECKSUM TABLE t2;
SELECT * FROM t4 ORDER BY c1;
UNLOCK TABLES;
+#
--echo #
--echo # Insert delayed
--echo #
---error ER_ILLEGAL_HA
+# See also Bug#26464 - insert delayed + update + merge = corruption
+# Succeeds in embedded server - is converted to normal insert
+# Fails in normal server, ps-protocol - not supported by engine
+# Fails in normal server, normal protocol - not a base table
+--error 0, ER_ILLEGAL_HA, ER_WRONG_OBJECT
INSERT DELAYED INTO t4 VALUES(44);
+# Get rid of row in embedded server
+DELETE FROM t4 WHERE c1 = 44;
INSERT DELAYED INTO t3 VALUES(33);
let $wait_cmd= SHOW STATUS LIKE 'Not_flushed_delayed_rows';
let $run= query_get_value($wait_cmd, Value, 1);
@@ -1084,6 +1186,19 @@ INSERT DELAYED INTO t3 VALUES(333);
SELECT * FROM t4 ORDER BY c1;
UNLOCK TABLES;
DROP TABLE t1, t2, t3, t4;
+#
+--echo #
+--echo # Recursive inclusion of merge tables in their union clauses.
+--echo #
+CREATE TABLE t1 (c1 INT, INDEX(c1));
+CREATE TABLE t2 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1)
+ INSERT_METHOD=LAST;
+CREATE TABLE t3 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t2,t1)
+ INSERT_METHOD=LAST;
+ALTER TABLE t2 UNION=(t3,t1);
+--error ER_ADMIN_WRONG_MRG_TABLE
+SELECT * FROM t2;
+DROP TABLE t1, t2, t3;
#
diff -Nrup a/sql/slave.cc b/sql/slave.cc
--- a/sql/slave.cc 2007-11-02 17:28:15 +01:00
+++ b/sql/slave.cc 2007-11-14 19:37:34 +01:00
@@ -1013,8 +1013,14 @@ static int create_table_from_dump(THD* t
goto err; // mysql_parse took care of the error send
thd->proc_info = "Opening master dump table";
- tables.table= NULL; /* was set by mysql_rm_table(). */
- if (!open_n_lock_single_table(thd, &tables, TL_WRITE))
+ /*
+ Note: If this function starts to fail for MERGE tables,
+ change the next two lines to these:
+ tables.table= NULL; // was set by mysql_rm_table()
+ if (!open_n_lock_single_table(thd, &tables, TL_WRITE))
+ */
+ tables.lock_type = TL_WRITE;
+ if (!open_ltable(thd, &tables, TL_WRITE, 0))
{
sql_print_error("create_table_from_dump: could not open created table");
goto err;
diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc 2007-11-02 17:28:15 +01:00
+++ b/sql/sql_base.cc 2007-11-14 19:37:34 +01:00
@@ -684,7 +684,7 @@ TABLE_SHARE *get_cached_table_share(cons
thd->killed will be set if we run out of memory
- If closing a MERGE child, the calling fuction has to take care for
+ If closing a MERGE child, the calling function has to take care for
closing the parent too, if necessary.
*/
@@ -848,9 +848,7 @@ static void free_cache_entry(TABLE *tabl
DBUG_ENTER("free_cache_entry");
/* Assert that MERGE children are not attached before final close. */
- DBUG_ASSERT((!table->child_l && !table->parent) ||
- (table->child_l && !table->children_attached) ||
- (table->parent && !table->parent->children_attached));
+ DBUG_ASSERT(!table->is_children_attached());
intern_close_table(table);
if (!table->in_use)
@@ -1382,9 +1380,7 @@ bool close_thread_table(THD *thd, TABLE
DBUG_ASSERT(!table->open_placeholder);
/* Assert that MERGE children are not attached in unused_tables. */
- DBUG_ASSERT((!table->child_l && !table->parent) ||
- (table->child_l && !table->children_attached) ||
- (table->parent && !table->parent->children_attached));
+ DBUG_ASSERT(!table->is_children_attached());
/* Free memory and reset for next loop */
table->file->ha_reset();
@@ -1935,9 +1931,7 @@ bool rename_temporary_table(THD* thd, TA
static void relink_unused(TABLE *table)
{
/* Assert that MERGE children are not attached in unused_tables. */
- DBUG_ASSERT((!table->child_l && !table->parent) ||
- (table->child_l && !table->children_attached) ||
- (table->parent && !table->parent->children_attached));
+ DBUG_ASSERT(!table->is_children_attached());
if (table != unused_tables)
{
@@ -1954,6 +1948,77 @@ static void relink_unused(TABLE *table)
/**
+ @brief Prepare an open merge table for close.
+
+ @param[in] thd thread context
+ @param[in] table table to prepare
+ @param[in,out] prev_pp pointer to pointer of previous table
+
+ @detail
+ If the table is a MERGE parent, just detach the children.
+ If the table is a MERGE child, close the parent (incl. detach).
+*/
+
+static void unlink_open_merge(THD *thd, TABLE *table, TABLE ***prev_pp)
+{
+ DBUG_ENTER("unlink_open_merge");
+
+ if (table->parent)
+ {
+ /*
+ If MERGE child, close parent too. Closing includes detaching.
+
+ This is used for example in ALTER TABLE t1 RENAME TO t5 under
+ LOCK TABLES where t1 is a MERGE child:
+ CREATE TABLE t1 (c1 INT);
+ CREATE TABLE t2 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1);
+ LOCK TABLES t1 WRITE, t2 WRITE;
+ ALTER TABLE t1 RENAME TO t5;
+ */
+ TABLE *parent= table->parent;
+ TABLE **prv_p;
+
+ /* Find parent in open_tables list. */
+ for (prv_p= &thd->open_tables;
+ *prv_p && (*prv_p != parent);
+ prv_p= &(*prv_p)->next) {}
+ if (*prv_p)
+ {
+ /* Special treatment required if child follows parent in list. */
+ if (*prev_pp == &parent->next)
+ *prev_pp= prv_p;
+ /*
+ Remove parent from open_tables list and close it.
+ This includes detaching and hence clearing parent references.
+ */
+ close_thread_table(thd, prv_p);
+ }
+ }
+ else if (table->child_l)
+ {
+ /*
+ When closing a MERGE parent, detach the children first. It is
+ not necessary to clear the child or parent table reference of
+ this table because the TABLE is freed. But we need to clear
+ the child or parent references of the other belonging tables
+ so that they cannot be moved into the unused_tables chain with
+ these pointers set.
+
+ This is used for example in ALTER TABLE t2 RENAME TO t5 under
+ LOCK TABLES where t2 is a MERGE parent:
+ CREATE TABLE t1 (c1 INT);
+ CREATE TABLE t2 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1);
+ LOCK TABLES t1 WRITE, t2 WRITE;
+ ALTER TABLE t2 RENAME TO t5;
+ */
+ detach_merge_children(table, TRUE);
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
+/**
@brief Remove all instances of table from thread's open list and
table cache.
@@ -1995,37 +2060,9 @@ void unlink_open_table(THD *thd, TABLE *
if (unlock && thd->locked_tables)
mysql_lock_remove(thd, thd->locked_tables,
list->parent ? list->parent : list, TRUE);
- if (list->parent)
- {
- /* If MERGE child, close parent too. Closing includes detaching. */
- TABLE *parent= list->parent;
- TABLE **prv_p;
-
- /* Find parent in open_tables list. */
- for (prv_p= &thd->open_tables;
- *prv_p && (*prv_p != parent);
- prv_p= &(*prv_p)->next) {}
- if (*prv_p)
- {
- /* Special treatment required if child follows parent in list. */
- if (prev == &parent->next)
- prev= prv_p;
- /* Remove parent from open_tables list and close it. */
- close_thread_table(thd, prv_p);
- }
- }
- else if (list->child_l)
- {
- /*
- When closing a MERGE parent, detach the children first. It is
- not necessary to clear the child or parent table reference of
- this table because the TABLE is freed. But we need to clear
- the child or parent references of the other belonging tables
- so that they cannot be moved into the unused_tables chain with
- these pointers set.
- */
- detach_merge_children(list, TRUE);
- }
+
+ /* Prepare MERGE table for close. Close parent if necessary. */
+ unlink_open_merge(thd, list, &prev);
/* Remove table from open_tables list. */
*prev= list->next;
@@ -3102,6 +3139,62 @@ void close_data_files_and_morph_locks(TH
/**
+ @brief Reattach MERGE children after reopen.
+
+ @param[in] thd thread context
+ @param[in,out] err_tables_p pointer to pointer of tables in error
+
+ @return status
+ @retval FALSE OK, err_tables_p unchanged
+ @retval TRUE Error, err_tables_p contains table(s)
+*/
+
+static bool reattach_merge(THD *thd, TABLE **err_tables_p)
+{
+ TABLE *table;
+ TABLE *next;
+ TABLE **prv_p= &thd->open_tables;
+ bool error= FALSE;
+ DBUG_ENTER("reattach_merge");
+
+ for (table= thd->open_tables; table; table= next)
+ {
+ next= table->next;
+ DBUG_PRINT("tcache", ("check table: '%s'.'%s' 0x%lx next: 0x%lx",
+ table->s->db.str, table->s->table_name.str,
+ (long) table, (long) next));
+ /* Reattach children for MERGE tables with "closed data files" only. */
+ if (table->child_l && !table->children_attached)
+ {
+ DBUG_PRINT("tcache", ("MERGE parent, attach children"));
+ if(table->file->extra(HA_EXTRA_ATTACH_CHILDREN))
+ {
+ my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
+ error= TRUE;
+ /* Remove table from open_tables. */
+ *prv_p= next;
+ if (next)
+ prv_p= &next->next;
+ /* Stack table on error list. */
+ table->next= *err_tables_p;
+ *err_tables_p= table;
+ continue;
+ }
+ else
+ {
+ table->children_attached= TRUE;
+ DBUG_PRINT("myrg", ("attached parent: '%s'.'%s' 0x%lx",
+ table->s->db.str,
+ table->s->table_name.str, (long) table));
+ }
+ }
+ prv_p= &table->next;
+ }
+ DBUG_RETURN(error);
+}
+
+
+/**
@brief Reopen all tables with closed data files.
@param thd Thread context
@@ -3125,6 +3218,7 @@ bool reopen_tables(THD *thd,bool get_loc
{
TABLE *table,*next,**prev;
TABLE **tables,**tables_ptr; // For locks
+ TABLE *err_tables= NULL;
bool error=0, not_used;
bool merge_table_found= FALSE;
DBUG_ENTER("reopen_tables");
@@ -3194,37 +3288,18 @@ bool reopen_tables(THD *thd,bool get_loc
}
}
}
+ *prev=0;
/*
When all tables are open again, we can re-attach MERGE children to
their parents. All TABLE objects are still present.
*/
DBUG_PRINT("tcache", ("re-attaching MERGE tables: %d", merge_table_found));
- if (!error && merge_table_found)
+ if (!error && merge_table_found && reattach_merge(thd, &err_tables))
{
- for (table= thd->open_tables; table; table= next)
+ while (err_tables)
{
- next= table->next;
- DBUG_PRINT("tcache", ("check table: '%s'.'%s' 0x%lx next: 0x%lx",
- table->s->db.str, table->s->table_name.str,
- (long) table, (long) next));
- /* Reattach children for MERGE tables with "closed data files" only. */
- if (table->child_l && !table->children_attached)
- {
- DBUG_PRINT("tcache", ("MERGE parent, attach children"));
- if(table->file->extra(HA_EXTRA_ATTACH_CHILDREN))
- {
- my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
- VOID(hash_delete(&open_cache, (uchar*) table));
- error=1;
- }
- else
- {
- table->children_attached= TRUE;
- DBUG_PRINT("myrg", ("attached parent: '%s'.'%s' 0x%lx",
- table->s->db.str,
- table->s->table_name.str, (long) table));
- }
- }
+ VOID(hash_delete(&open_cache, (uchar*) err_tables));
+ err_tables= err_tables->next;
}
}
DBUG_PRINT("tcache", ("open tables to lock: %u",
@@ -3259,7 +3334,6 @@ bool reopen_tables(THD *thd,bool get_loc
my_afree((uchar*) tables);
}
broadcast_refresh();
- *prev=0;
DBUG_RETURN(error);
}
@@ -3816,16 +3890,17 @@ err:
/**
@brief Add list of MERGE children to a TABLE_LIST list.
- @detail When a MERGE parent table has just been opened, insert the
- TABLE_LIST chain from the MERGE handle into the table list used for
- opening tables for this statement. This lets the children be opened
- too.
-
- @param[in] tlist the TABLE_LIST object just opened
+ @param[in] tlist the parent TABLE_LIST object just opened
@return status
@retval 0 OK
@retval != 0 Error
+
+ @detail
+ When a MERGE parent table has just been opened, insert the
+ TABLE_LIST chain from the MERGE handle into the table list used for
+ opening tables for this statement. This lets the children be opened
+ too.
*/
static int add_merge_table_list(TABLE_LIST *tlist)
@@ -3840,6 +3915,12 @@ static int add_merge_table_list(TABLE_LI
DBUG_ASSERT(!parent->children_attached);
/* Must not call this with children list in place. */
DBUG_ASSERT(tlist->next_global != parent->child_l);
+ /* Prevent inclusion of another MERGE table. Could make infinite recursion. */
+ if (tlist->parent_l)
+ {
+ my_error(ER_ADMIN_WRONG_MRG_TABLE, MYF(0), tlist->alias);
+ DBUG_RETURN(1);
+ }
/* Fix children.*/
for (child_l= parent->child_l; ; child_l= child_l->next_global)
@@ -3878,16 +3959,17 @@ static int add_merge_table_list(TABLE_LI
/**
@brief Attach MERGE children to the parent.
- @detail When the last MERGE child has just been opened, let the
- handler attach the MyISAM tables to the MERGE table. Remove MERGE
- TABLE_LIST chain from the statement list so that it cannot be
- changed or freed.
-
- @param[in] tlist the TABLE_LIST object just opened
+ @param[in] tlist the child TABLE_LIST object just opened
@return status
@retval 0 OK
@retval != 0 Error
+
+ @note
+ This is called when the last MERGE child has just been opened, let
+ the handler attach the MyISAM tables to the MERGE table. Remove
+ MERGE TABLE_LIST chain from the statement list so that it cannot be
+ changed or freed.
*/
static int attach_merge_children(TABLE_LIST *tlist)
@@ -4055,13 +4137,27 @@ void detach_merge_children(TABLE *table,
@retval FALSE OK, no mismatch
@retval TRUE Error, lists mismatch
- @detail Main action is to copy TABLE reference for each member of
- original child list to new child list. After a fresh open these
- references are NULL. Assign the old children to the new table.
- Some of them might also be reopened or will be reopened soon.
+ @detail
+ Main action is to copy TABLE reference for each member of original
+ child list to new child list. After a fresh open these references
+ are NULL. Assign the old children to the new table. Some of them
+ might also be reopened or will be reopened soon.
Other action is to verify that the table definition with respect to
the UNION list did not change.
+
+ @note
+ This function terminates the child list if the respective '*_last'
+ pointer is non-NULL. Do not call it from a place where the list is
+ embedded in another list and this would break it.
+
+ Terminating the list is required for example in the first
+ reopen_table() after open_tables(). open_tables() requires the end
+ of the list not to be terminated because other tables could follow
+ behind the child list.
+
+ If a '*_last' pointer is NULL, the respective list is assumed to be
+ NULL terminated.
*/
bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last,
@@ -4072,6 +4168,12 @@ bool fix_merge_after_open(TABLE_LIST *ol
DBUG_PRINT("myrg", ("old last addr: 0x%lx new last addr: 0x%lx",
(long) old_last, (long) new_last));
+ /* Terminate the lists for easier check of list end. */
+ if (old_last)
+ *old_last= NULL;
+ if (new_last)
+ *new_last= NULL;
+
for (;;)
{
DBUG_PRINT("myrg", ("old list item: 0x%lx new list item: 0x%lx",
@@ -4089,10 +4191,7 @@ bool fix_merge_after_open(TABLE_LIST *ol
/* Child db.table names must match. */
if (strcmp(old_child_list->table_name, new_child_list->table_name) ||
strcmp(old_child_list->db, new_child_list->db))
- {
- mismatch= TRUE;
break;
- }
/*
Copy TABLE reference. Child TABLE objects are still in place
though not necessarily open yet.
@@ -4101,35 +4200,19 @@ bool fix_merge_after_open(TABLE_LIST *ol
(long) old_child_list->table,
(long) new_child_list->table));
new_child_list->table= old_child_list->table;
- /*
- Break if one of the lists is at its last child. When the child
- list is part of the statement list, the list may continue after
- the last child. The test for NULL is insufficient.
- */
- DBUG_PRINT("myrg", ("old next addr: 0x%lx new next addr: 0x%lx",
- (long) &old_child_list->next_global,
- (long) &new_child_list->next_global));
- if ((old_last && (&old_child_list->next_global == old_last)) ||
- (new_last && (&new_child_list->next_global == new_last)))
- break;
/* Step both lists. */
old_child_list= old_child_list->next_global;
new_child_list= new_child_list->next_global;
}
DBUG_PRINT("myrg", ("end of list, mismatch: %d", mismatch));
- if (!mismatch &&
- (/* old list at end */
- (!old_child_list || (!old_last && !old_child_list->next_global) ||
- (old_last && (&old_child_list->next_global == old_last))) &&
- /* and new list not at end */
- (new_child_list && new_child_list->next_global &&
- (!new_last || (&new_child_list->next_global != new_last)))) ||
- (/* new list at end */
- (!new_child_list || (!new_last && !new_child_list->next_global) ||
- (new_last && (&new_child_list->next_global == new_last))) &&
- /* and old list not at end */
- (old_child_list && old_child_list->next_global &&
- (!old_last || (&old_child_list->next_global != old_last)))))
+ /*
+ If the list pointers are not both NULL after the loop, then the
+ lists differ. If the are both identical, but not NULL, then they
+ have at least one table in common and hence the rest of the list
+ would be identical too. But in this case the loop woul run until the
+ list end, where both pointers would become NULL.
+ */
+ if (old_child_list != new_child_list)
mismatch= TRUE;
if (mismatch)
my_error(ER_TABLE_DEF_CHANGED, MYF(0));
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc 2007-11-02 17:28:15 +01:00
+++ b/sql/sql_insert.cc 2007-11-14 19:37:34 +01:00
@@ -3372,7 +3372,6 @@ static TABLE *create_table_from_items(TH
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
- /* Non-temporary table. */
VOID(pthread_mutex_lock(&LOCK_open));
if (reopen_name_locked_table(thd, create_table, FALSE))
{
@@ -3383,50 +3382,9 @@ static TABLE *create_table_from_items(TH
else
table= create_table->table;
VOID(pthread_mutex_unlock(&LOCK_open));
-
- /*
- Non-temporary MERGE parent and children need be open, attached
- and locked for select. The children have been opened and
- locked at statement begin through the UNION=() clause of the
- CREATE TABLE part of the statement. A simple CREATE TABLE does
- not open any table. But CREATE...SELECT opens all tables,
- including the MERGE child tables.
-
- We cannot use the existing locks of the children directly. For
- replication we need an 'extra_lock' on the parent table. We
- cannot first unlock the children and then lock them through
- the parent. This would allow other threads to step in.
-
- So we need new TABLE objects for the children so that they can
- be locked through the parent. Later we remove the locks from
- the original child TABLEs.
- */
- if (table && table->child_l)
- {
- uint counter;
- /* Assert that child list is terminated. */
- DBUG_ASSERT(!*table->child_last_l);
- if (open_tables(thd, &create_table->table->child_l, &counter,
- MYSQL_LOCK_IGNORE_FLUSH) ||
- table->file->extra(HA_EXTRA_ATTACH_CHILDREN))
- {
- if (!create_info->table_existed)
- drop_open_table(thd, table, create_table->db,
- create_table->table_name);
- table= NULL;
- }
- else
- {
- table->children_attached= TRUE;
- DBUG_PRINT("myrg", ("attached parent: '%s'.'%s' 0x%lx",
- table->s->db.str,
- table->s->table_name.str, (long) table));
- }
- }
}
else
{
- /* Temporary table. */
if (!(table= open_table(thd, create_table, thd->mem_root, (bool*) 0,
MYSQL_OPEN_TEMPORARY_ONLY)) &&
!create_info->table_existed)
@@ -3438,37 +3396,6 @@ static TABLE *create_table_from_items(TH
*/
close_temporary_table(thd, create_table);
}
-
- /*
- Temporary MERGE parent and children need be open and attached
- for select. The children have been opened at statement begin
- through the UNION=() clause of the CREATE TABLE part of the
- statement. A simple CREATE TABLE does not open any table. But
- CREATE...SELECT opens all tables, including the MERGE child
- tables.
-
- We can just use the open children since we do not lock
- temporary tables. Note that a temporary MERGE table must have
- temporary children. So grab open MERGE children from
- create_info->merge_list.
- */
- if (table && table->child_l)
- {
- if (fix_merge_after_open((TABLE_LIST*) create_info->merge_list.first,
- NULL, table->child_l, table->child_last_l) ||
- table->file->extra(HA_EXTRA_ATTACH_CHILDREN))
- {
- close_temporary_table(thd, create_table);
- table= NULL;
- }
- else
- {
- table->children_attached= TRUE;
- DBUG_PRINT("myrg", ("attached parent: '%s'.'%s' 0x%lx",
- table->s->db.str,
- table->s->table_name.str, (long) table));
- }
- }
}
}
reenable_binlog(thd);
@@ -3497,19 +3424,6 @@ static TABLE *create_table_from_items(TH
if (!create_info->table_existed)
drop_open_table(thd, table, create_table->db, create_table->table_name);
DBUG_RETURN(0);
- }
-
- /*
- For a non-temporary MERGE table we have now extra locks on the
- children through the parent. We need to remove the locks from the
- original child TABLEs.
- */
- if (table->child_l && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
- {
- TABLE_LIST *tlist= (TABLE_LIST*) create_info->merge_list.first;
- for (; tlist; tlist= tlist->next_global)
- mysql_lock_remove(thd, thd->lock ? thd->lock : thd->locked_tables,
- tlist->table, FALSE);
}
DBUG_RETURN(table);
}
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc 2007-11-02 17:28:15 +01:00
+++ b/sql/sql_parse.cc 2007-11-14 19:37:34 +01:00
@@ -488,8 +488,8 @@ end:
every child. Set 'db' for every child if not present.
*/
-static bool check_merge_table_access_fix_locks(THD *thd, char *db,
- TABLE_LIST *table_list)
+static bool check_merge_table_access(THD *thd, char *db,
+ TABLE_LIST *table_list)
{
int error= 0;
@@ -500,12 +500,6 @@ static bool check_merge_table_access_fix
for (tlist= table_list; tlist; tlist= tlist->next_local)
{
- /*
- We create or alter a MERGE table. In both cases the MERGE child
- tables must be locked in write mode.
- */
- tlist->lock_type= TL_WRITE;
-
if (!tlist->db || !tlist->db[0])
tlist->db= db; /* purecov: inspected */
}
@@ -587,7 +581,8 @@ int mysql_table_dump(THD *thd, LEX_STRIN
if (lower_case_table_names)
my_casedn_str(files_charset_info, tbl_name);
- if (!(table= open_n_lock_single_table(thd, table_list, TL_READ_NO_INSERT)))
+ if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT, 0)))
+ //if (!(table= open_n_lock_single_table(thd, table_list, TL_READ_NO_INSERT)))
DBUG_RETURN(1);
if (check_one_table_access(thd, SELECT_ACL, table_list))
@@ -2300,6 +2295,19 @@ mysql_execute_command(THD *thd)
select_lex->options|= SELECT_NO_UNLOCK;
unit->set_limit(select_lex);
+ /*
+ Disable non-empty MERGE tables with CREATE...SELECT. Too
+ complicated. See Bug #26379. Empty MERGE tables are read-only
+ and don't allow CREATE...SELECT anyway.
+ */
+ if (create_info.used_fields & HA_CREATE_USED_UNION)
+ {
+ my_error(ER_WRONG_OBJECT, MYF(0), create_table->db,
+ create_table->table_name, "BASE TABLE");
+ res= 1;
+ goto end_with_restore_list;
+ }
+
if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
lex->link_first_table_back(create_table, link_to_local);
@@ -2496,9 +2504,9 @@ end_with_restore_list:
test(first_table->schema_table)) ||
check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0,
is_schema_db(select_lex->db))||
- check_merge_table_access_fix_locks(thd, first_table->db,
- (TABLE_LIST *)
- create_info.merge_list.first))
+ check_merge_table_access(thd, first_table->db,
+ (TABLE_LIST *)
+ create_info.merge_list.first))
goto error; /* purecov: inspected */
if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0))
goto error;
@@ -7004,9 +7012,9 @@ bool create_table_precheck(THD *thd, TAB
if (check_access(thd, want_priv, create_table->db,
&create_table->grant.privilege, 0, 0,
test(create_table->schema_table)) ||
- check_merge_table_access_fix_locks(thd, create_table->db,
- (TABLE_LIST *)
- lex->create_info.merge_list.first))
+ check_merge_table_access(thd, create_table->db,
+ (TABLE_LIST *)
+ lex->create_info.merge_list.first))
goto err;
if (want_priv != CREATE_TMP_ACL &&
check_grant(thd, want_priv, create_table, 0, 1, 0))
diff -Nrup a/sql/sql_table.cc b/sql/sql_table.cc
--- a/sql/sql_table.cc 2007-11-02 17:28:16 +01:00
+++ b/sql/sql_table.cc 2007-11-14 19:37:34 +01:00
@@ -3827,16 +3827,8 @@ static int prepare_for_restore(THD* thd,
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed to open partially restored table"));
}
- if (table->table && table->table->child_l)
- {
- /* A MERGE table must not come here. */
- /* purecov: begin inspected */
- unlock_table_name(thd, table);
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(send_check_errmsg(thd, table, "restore",
- "Not supported for MERGE tables"));
- /* purecov: end */
- }
+ /* A MERGE table must not come here. */
+ DBUG_ASSERT(!table->table || !table->table->child_l);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0);
}
@@ -3880,15 +3872,8 @@ static int prepare_for_repair(THD *thd,
pthread_mutex_unlock(&LOCK_open);
}
- if (table->child_l)
- {
- /* A MERGE table must not come here. */
- /* purecov: begin inspected */
- error= send_check_errmsg(thd, table_list, "repair",
- "Not supported for MERGE tables");
- goto end;
- /* purecov: end */
- }
+ /* A MERGE table must not come here. */
+ DBUG_ASSERT(!table->child_l);
/*
REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
@@ -5870,6 +5855,20 @@ view_err:
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
DBUG_RETURN(TRUE);
table->use_all_columns();
+
+ /*
+ Prohibit changing of the UNION list of a non-temporary MERGE table
+ under LOCK tables. It would be quite difficult to reuse a shrinked
+ set of tables from the old table or to open a new TABLE object for
+ an extended list and verify that they belong to locked tables.
+ */
+ if (thd->locked_tables &&
+ (create_info->used_fields & HA_CREATE_USED_UNION) &&
+ (table->s->tmp_table == NO_TMP_TABLE))
+ {
+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
/* Check that we are not trying to rename to an existing table */
if (new_name)
diff -Nrup a/sql/table.cc b/sql/table.cc
--- a/sql/table.cc 2007-11-02 17:28:16 +01:00
+++ b/sql/table.cc 2007-11-14 19:37:34 +01:00
@@ -4477,6 +4477,25 @@ void st_table::mark_columns_needed_for_i
mark_auto_increment_column();
}
+
+/**
+ @brief Check if this is part of a MERGE table with attached children.
+
+ @return status
+ @retval TRUE children are attached
+ @retval FALSE no MERGE part or children not attached
+
+ @detail
+ A MERGE table consists of a parent TABLE and zero or more child
+ TABLEs. Each of these TABLEs is called a part of a MERGE table.
+*/
+
+bool st_table::is_children_attached(void)
+{
+ return((child_l && children_attached) ||
+ (parent && parent->children_attached));
+}
+
/*
Cleanup this table for re-execution.
diff -Nrup a/sql/table.h b/sql/table.h
--- a/sql/table.h 2007-11-02 17:28:16 +01:00
+++ b/sql/table.h 2007-11-14 19:37:34 +01:00
@@ -668,6 +668,7 @@ struct st_table {
*/
inline bool needs_reopen_or_name_lock()
{ return s->version != refresh_version; }
+ bool is_children_attached(void);
};
enum enum_schema_table_state
diff -Nrup a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
--- a/storage/myisam/ha_myisam.cc 2007-11-02 17:28:16 +01:00
+++ b/storage/myisam/ha_myisam.cc 2007-11-14 19:37:34 +01:00
@@ -2124,25 +2124,3 @@ my_bool ha_myisam::register_query_cache_
}
#endif
-
-/**
- @brief Extract the MyISAM table structure pointer from a handler object.
-
- @param[in] handler_handle pointer to handler object
-
- @return MyISAM table structure pointer
- @retval !=NULL Ok, returning pointer
- @retval NULL Error: handler has not a MyISAM table open
-*/
-
-MI_INFO *myisam_engine_handle(handler *handler_handle)
-{
- DBUG_ENTER("myisam_engine_handle");
- if (handler_handle->ht->db_type != DB_TYPE_MYISAM)
- {
- DBUG_PRINT("error", ("not a MyISAM table"));
- DBUG_RETURN(NULL);
- }
- DBUG_RETURN(((ha_myisam*) handler_handle)->file);
-}
-
diff -Nrup a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
--- a/storage/myisam/ha_myisam.h 2007-11-02 17:28:16 +01:00
+++ b/storage/myisam/ha_myisam.h 2007-11-14 19:37:34 +01:00
@@ -33,8 +33,6 @@ extern ulong myisam_sort_buffer_size;
extern TYPELIB myisam_recover_typelib;
extern ulong myisam_recover_options;
-extern MI_INFO *myisam_engine_handle(handler *handler_handle);
-
class ha_myisam: public handler
{
MI_INFO *file;
@@ -142,6 +140,8 @@ class ha_myisam: public handler
*engine_callback,
ulonglong *engine_data);
#endif
-
- friend MI_INFO *myisam_engine_handle(handler *handler_handle);
+ MI_INFO *file_ptr(void)
+ {
+ return file;
+ }
};
diff -Nrup a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
--- a/storage/myisammrg/ha_myisammrg.cc 2007-11-02 17:28:16 +01:00
+++ b/storage/myisammrg/ha_myisammrg.cc 2007-11-14 19:37:34 +01:00
@@ -46,6 +46,12 @@
tables. The children are opened as independent MyISAM tables, right as
if they are used by the SQL statement.
+ TABLE_LIST::parent_l is required to find the parent 1. when the last
+ child has been opened and children are to be attached, and 2. when an
+ error happens during child open and the child list must be removed
+ from the queuery list. In these cases the current child does not have
+ TABLE::parent set or does not have a TABLE at all respectively.
+
When the last child is open, attach_merge_children() is called. It
removes the list of children from the open list. Then the children are
"attached" to the parent. All required references between parent and
@@ -57,6 +63,9 @@
Every child TABLE::parent references the parent TABLE object. That way
TABLE objects belonging to a MERGE table can be identified.
+ TABLE::parent is required because the parent and child TABLE objects
+ can live longer than the parent TABLE_LIST object. So the path
+ child->pos_in_table_list->parent_l->table can be broken.
If necessary, the compatibility of parent and children is checked.
This check is necessary when any of the objects are reopend. This is
@@ -361,7 +370,8 @@ static MI_INFO *myisammrg_attach_childre
}
/* Extract the MyISAM table structure pointer from the handler object. */
- if (!(myisam= myisam_engine_handle(child->file)))
+ if ((child->file->ht->db_type != DB_TYPE_MYISAM) ||
+ !(myisam= ((ha_myisam*) child->file)->file_ptr()))
{
DBUG_PRINT("error", ("no MyISAM handle for child table: '%s'.'%s' 0x%lx",
child->s->db.str, child->s->table_name.str,
| Thread |
|---|
| • bk commit into 5.1 tree (istruewing:1.2596) BUG#26379 | Ingo Struewing | 14 Nov |