summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Vojtovich <svoj@mysql.com>2009-02-12 14:25:12 +0400
committerSergey Vojtovich <svoj@mysql.com>2009-02-12 14:25:12 +0400
commit984c2489d11455d5c4cfaf25fd18e062970d96a9 (patch)
treefa0cc70c075870d07457de190a82f9c1e45993f8
parent5103b05dd567c8c0c115c5cb3838af4b2d1fb9ad (diff)
parente80537b7912b4790817e3afb6fc3f84f3a82d224 (diff)
downloadmariadb-git-984c2489d11455d5c4cfaf25fd18e062970d96a9.tar.gz
Merge 5.1-bugteam -> 5.1-bugteam (local).
-rw-r--r--mysql-test/r/merge.result45
-rw-r--r--mysql-test/t/merge.test52
-rw-r--r--storage/myisammrg/ha_myisammrg.cc79
-rw-r--r--storage/myisammrg/ha_myisammrg.h2
-rw-r--r--storage/myisammrg/myrg_open.c2
5 files changed, 171 insertions, 9 deletions
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index b3d73f1225f..3910536ee5d 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -2025,7 +2025,6 @@ TABLE_SCHEMA = 'test' and TABLE_NAME='tm1';
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT
NULL test tm1 BASE TABLE NULL NULL NULL # # # # # # # # # # NULL # # Unable to open underlying table which is differently defined or of non-MyISAM ty
DROP TABLE tm1;
-End of 5.1 tests
CREATE TABLE t1(C1 INT, C2 INT, KEY C1(C1), KEY C2(C2)) ENGINE=MYISAM;
CREATE TABLE t2(C1 INT, C2 INT, KEY C1(C1), KEY C2(C2)) ENGINE=MYISAM;
CREATE TABLE t3(C1 INT, C2 INT, KEY C1(C1), KEY C2(C2)) ENGINE=MYISAM;
@@ -2060,4 +2059,48 @@ SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test'
CARDINALITY
5
DROP TABLE t1, m1;
+#
+# Bug #40675 MySQL 5.1 crash with index merge algorithm and Merge tables
+#
+# create MYISAM table t1 and insert values into it
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1);
+# create MYISAM table t2 and insert values into it
+CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b));
+INSERT INTO t2(a,b) VALUES
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(1,2);
+# Create the merge table t3
+CREATE TABLE t3(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b))
+ENGINE=MERGE UNION=(t2) INSERT_METHOD=FIRST;
+# Lock tables t1 and t3 for write
+LOCK TABLES t1 WRITE, t3 WRITE;
+# Insert values into the merge table t3
+INSERT INTO t3(a,b) VALUES(1,2);
+# select from the join of t2 and t3 (The merge table)
+SELECT t3.a FROM t1,t3 WHERE t3.b=2 AND t3.a=1;
+a
+1
+1
+# Unlock the tables
+UNLOCK TABLES;
+# drop the created tables
+DROP TABLE t1, t2, t3;
End of 5.1 tests
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index e8c514f3804..2fbfe2721e2 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -1418,8 +1418,6 @@ TABLE_SCHEMA = 'test' and TABLE_NAME='tm1';
DROP TABLE tm1;
---echo End of 5.1 tests
-
#
# Bug#36006 - Optimizer does table scan for select count(*)
#
@@ -1448,4 +1446,54 @@ SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test'
SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1';
DROP TABLE t1, m1;
+--echo #
+--echo # Bug #40675 MySQL 5.1 crash with index merge algorithm and Merge tables
+--echo #
+
+--echo # create MYISAM table t1 and insert values into it
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1);
+
+--echo # create MYISAM table t2 and insert values into it
+CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b));
+INSERT INTO t2(a,b) VALUES
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(1,2);
+
+--echo # Create the merge table t3
+CREATE TABLE t3(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b))
+ENGINE=MERGE UNION=(t2) INSERT_METHOD=FIRST;
+
+--echo # Lock tables t1 and t3 for write
+LOCK TABLES t1 WRITE, t3 WRITE;
+
+--echo # Insert values into the merge table t3
+INSERT INTO t3(a,b) VALUES(1,2);
+
+--echo # select from the join of t2 and t3 (The merge table)
+SELECT t3.a FROM t1,t3 WHERE t3.b=2 AND t3.a=1;
+
+--echo # Unlock the tables
+UNLOCK TABLES;
+
+--echo # drop the created tables
+DROP TABLE t1, t2, t3;
+
--echo End of 5.1 tests
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 956f0e421cc..d674f6bc150 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -116,7 +116,7 @@ static handler *myisammrg_create_handler(handlerton *hton,
*/
ha_myisammrg::ha_myisammrg(handlerton *hton, TABLE_SHARE *table_arg)
- :handler(hton, table_arg), file(0)
+ :handler(hton, table_arg), file(0), is_cloned(0)
{}
@@ -413,7 +413,28 @@ int ha_myisammrg::open(const char *name, int mode __attribute__((unused)),
/* retrieve children table list. */
my_errno= 0;
- if (!(file= myrg_parent_open(name, myisammrg_parent_open_callback, this)))
+ if (is_cloned)
+ {
+ /*
+ Open and attaches the MyISAM tables,that are under the MERGE table
+ parent, on the MyISAM storage engine interface directly within the
+ MERGE engine. The new MyISAM table instances, as well as the MERGE
+ clone itself, are not visible in the table cache. This is not a
+ problem because all locking is handled by the original MERGE table
+ from which this is cloned of.
+ */
+ if (!(file= myrg_open(table->s->normalized_path.str, table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED)))
+ {
+ DBUG_PRINT("error", ("my_errno %d", my_errno));
+ DBUG_RETURN(my_errno ? my_errno : -1);
+ }
+
+ file->children_attached= TRUE;
+
+ info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
+ }
+ else if (!(file= myrg_parent_open(name, myisammrg_parent_open_callback, this)))
{
DBUG_PRINT("error", ("my_errno %d", my_errno));
DBUG_RETURN(my_errno ? my_errno : -1);
@@ -422,6 +443,55 @@ int ha_myisammrg::open(const char *name, int mode __attribute__((unused)),
DBUG_RETURN(0);
}
+/**
+ Returns a cloned instance of the current handler.
+
+ @return A cloned handler instance.
+ */
+handler *ha_myisammrg::clone(MEM_ROOT *mem_root)
+{
+ MYRG_TABLE *u_table,*newu_table;
+ ha_myisammrg *new_handler=
+ (ha_myisammrg*) get_new_handler(table->s, mem_root, table->s->db_type());
+ if (!new_handler)
+ return NULL;
+
+ /* Inform ha_myisammrg::open() that it is a cloned handler */
+ new_handler->is_cloned= TRUE;
+ /*
+ Allocate handler->ref here because otherwise ha_open will allocate it
+ on this->table->mem_root and we will not be able to reclaim that memory
+ when the clone handler object is destroyed.
+ */
+ if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
+ {
+ delete new_handler;
+ return NULL;
+ }
+
+ if (new_handler->ha_open(table, table->s->normalized_path.str, table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED))
+ {
+ delete new_handler;
+ return NULL;
+ }
+
+ /*
+ Iterate through the original child tables and
+ copy the state into the cloned child tables.
+ We need to do this because all the child tables
+ can be involved in delete.
+ */
+ newu_table= new_handler->file->open_tables;
+ for (u_table= file->open_tables; u_table < file->end_table; u_table++)
+ {
+ newu_table->table->state= u_table->table->state;
+ newu_table++;
+ }
+
+ return new_handler;
+ }
+
/**
@brief Attach children to a MERGE table.
@@ -613,9 +683,10 @@ int ha_myisammrg::close(void)
DBUG_ENTER("ha_myisammrg::close");
/*
Children must not be attached here. Unless the MERGE table has no
- children. In this case children_attached is always true.
+ children or the handler instance has been cloned. In these cases
+ children_attached is always true.
*/
- DBUG_ASSERT(!this->file->children_attached || !this->file->tables);
+ DBUG_ASSERT(!this->file->children_attached || !this->file->tables || this->is_cloned);
rc= myrg_close(file);
file= 0;
DBUG_RETURN(rc);
diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h
index 4e7ddebb836..21d41c9d75a 100644
--- a/storage/myisammrg/ha_myisammrg.h
+++ b/storage/myisammrg/ha_myisammrg.h
@@ -25,6 +25,7 @@
class ha_myisammrg: public handler
{
MYRG_INFO *file;
+ my_bool is_cloned; /* This instance has been cloned */
public:
TABLE_LIST *next_child_attach; /* next child to attach */
@@ -60,6 +61,7 @@ class ha_myisammrg: public handler
int open(const char *name, int mode, uint test_if_locked);
int attach_children(void);
int detach_children(void);
+ virtual handler *clone(MEM_ROOT *mem_root);
int close(void);
int write_row(uchar * buf);
int update_row(const uchar * old_data, uchar * new_data);
diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c
index 69d2d2d0608..14ba2853b22 100644
--- a/storage/myisammrg/myrg_open.c
+++ b/storage/myisammrg/myrg_open.c
@@ -33,7 +33,6 @@
myrg_attach_children(). Please duplicate changes in these
functions or make common sub-functions.
*/
-/* purecov: begin deadcode */ /* not used in MySQL server */
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{
@@ -198,7 +197,6 @@ err:
my_errno=save_errno;
DBUG_RETURN (NULL);
}
-/* purecov: end */
/**