diff options
-rw-r--r-- | mysql-test/r/merge.result | 67 | ||||
-rw-r--r-- | mysql-test/std_data/bug48265.frm | bin | 0 -> 8554 bytes | |||
-rw-r--r-- | mysql-test/t/merge.test | 57 | ||||
-rw-r--r-- | storage/myisammrg/ha_myisammrg.cc | 126 | ||||
-rw-r--r-- | storage/myisammrg/myrg_open.c | 8 |
5 files changed, 205 insertions, 53 deletions
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 893ea5acf88..184cd92e053 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -2219,4 +2219,71 @@ Trigger sql_mode SQL Original Statement character_set_client collation_connectio tr1 CREATE DEFINER=`root`@`localhost` TRIGGER tr1 AFTER INSERT ON t3 FOR EACH ROW CALL foo() latin1 latin1_swedish_ci latin1_swedish_ci DROP TRIGGER tr1; DROP TABLE t1, t2, t3; +# +# BUG#48265 - MRG_MYISAM problem (works in 5.0.85, does't work in 5.1.40) +# +CREATE DATABASE `test/1`; +CREATE TABLE `test/1`.`t/1`(a INT); +CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(`test/1`.`t/1`); +SELECT * FROM m1; +a +SHOW CREATE TABLE m1; +Table Create Table +m1 CREATE TABLE `m1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`test/1`.`t/1`) +DROP TABLE m1; +CREATE TABLE `test/1`.m1(a INT) ENGINE=MERGE UNION=(`test/1`.`t/1`); +SELECT * FROM `test/1`.m1; +a +SHOW CREATE TABLE `test/1`.m1; +Table Create Table +m1 CREATE TABLE `m1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t/1`) +DROP TABLE `test/1`.m1; +DROP TABLE `test/1`.`t/1`; +CREATE TEMPORARY TABLE `test/1`.`t/1`(a INT); +CREATE TEMPORARY TABLE m1(a INT) ENGINE=MERGE UNION=(`test/1`.`t/1`); +SELECT * FROM m1; +a +SHOW CREATE TABLE m1; +Table Create Table +m1 CREATE TEMPORARY TABLE `m1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`test/1`.`t/1`) +DROP TABLE m1; +CREATE TEMPORARY TABLE `test/1`.m1(a INT) ENGINE=MERGE UNION=(`test/1`.`t/1`); +SELECT * FROM `test/1`.m1; +a +SHOW CREATE TABLE `test/1`.m1; +Table Create Table +m1 CREATE TEMPORARY TABLE `m1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t/1`) +DROP TABLE `test/1`.m1; +DROP TABLE `test/1`.`t/1`; +DROP DATABASE `test/1`; +CREATE TABLE `t@1`(a INT); +SELECT * FROM m1; +a +SHOW CREATE TABLE m1; +Table Create Table +m1 CREATE TABLE `m1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t@1`) +DROP TABLE `t@1`; +CREATE DATABASE `test@1`; +CREATE TABLE `test@1`.`t@1`(a INT); +FLUSH TABLE m1; +SELECT * FROM m1; +a +SHOW CREATE TABLE m1; +Table Create Table +m1 CREATE TABLE `m1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`test@1`.`t@1`) +DROP TABLE m1; +DROP TABLE `test@1`.`t@1`; +DROP DATABASE `test@1`; End of 5.1 tests diff --git a/mysql-test/std_data/bug48265.frm b/mysql-test/std_data/bug48265.frm Binary files differnew file mode 100644 index 00000000000..0a731964996 --- /dev/null +++ b/mysql-test/std_data/bug48265.frm diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 015ae28c155..d88467cc7a9 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -7,6 +7,8 @@ drop table if exists t1,t2,t3,t4,t5,t6; drop database if exists mysqltest; --enable_warnings +let $MYSQLD_DATADIR= `select @@datadir`; + create table t1 (a int not null primary key auto_increment, message char(20)); create table t2 (a int not null primary key auto_increment, message char(20)); INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1"); @@ -1633,4 +1635,59 @@ SHOW CREATE TRIGGER tr1; DROP TRIGGER tr1; DROP TABLE t1, t2, t3; +--echo # +--echo # BUG#48265 - MRG_MYISAM problem (works in 5.0.85, does't work in 5.1.40) +--echo # +CREATE DATABASE `test/1`; + +CREATE TABLE `test/1`.`t/1`(a INT); +CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(`test/1`.`t/1`); +SELECT * FROM m1; +SHOW CREATE TABLE m1; +DROP TABLE m1; + +CREATE TABLE `test/1`.m1(a INT) ENGINE=MERGE UNION=(`test/1`.`t/1`); +SELECT * FROM `test/1`.m1; +SHOW CREATE TABLE `test/1`.m1; +DROP TABLE `test/1`.m1; +DROP TABLE `test/1`.`t/1`; + +CREATE TEMPORARY TABLE `test/1`.`t/1`(a INT); +CREATE TEMPORARY TABLE m1(a INT) ENGINE=MERGE UNION=(`test/1`.`t/1`); +SELECT * FROM m1; +SHOW CREATE TABLE m1; +DROP TABLE m1; + +CREATE TEMPORARY TABLE `test/1`.m1(a INT) ENGINE=MERGE UNION=(`test/1`.`t/1`); +SELECT * FROM `test/1`.m1; +SHOW CREATE TABLE `test/1`.m1; +DROP TABLE `test/1`.m1; +DROP TABLE `test/1`.`t/1`; + +DROP DATABASE `test/1`; + +# Test compatibility. Use '@' instead of '/' (was not allowed in 5.0) + +CREATE TABLE `t@1`(a INT); +copy_file std_data/bug48265.frm $MYSQLD_DATADIR/test/m1.frm; +write_file $MYSQLD_DATADIR/test/m1.MRG; +t@1 +EOF +SELECT * FROM m1; +SHOW CREATE TABLE m1; +DROP TABLE `t@1`; + +CREATE DATABASE `test@1`; +CREATE TABLE `test@1`.`t@1`(a INT); +FLUSH TABLE m1; +remove_file $MYSQLD_DATADIR/test/m1.MRG; +write_file $MYSQLD_DATADIR/test/m1.MRG; +./test@1/t@1 +EOF +SELECT * FROM m1; +SHOW CREATE TABLE m1; +DROP TABLE m1; +DROP TABLE `test@1`.`t@1`; +DROP DATABASE `test@1`; + --echo End of 5.1 tests diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 8af776f5c5e..bf1b757a5c8 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -214,36 +214,14 @@ const char *ha_myisammrg::index_type(uint key_number) static int myisammrg_parent_open_callback(void *callback_param, const char *filename) { - ha_myisammrg *ha_myrg; - TABLE *parent; + ha_myisammrg *ha_myrg= (ha_myisammrg*) callback_param; + TABLE *parent= ha_myrg->table_ptr(); TABLE_LIST *child_l; - const char *db; - const char *table_name; size_t dirlen; char dir_path[FN_REFLEN]; + char name_buf[NAME_LEN]; DBUG_ENTER("myisammrg_parent_open_callback"); - /* Extract child table name and database name from filename. */ - dirlen= dirname_length(filename); - if (dirlen >= FN_REFLEN) - { - /* purecov: begin inspected */ - DBUG_PRINT("error", ("name too long: '%.64s'", filename)); - my_errno= ENAMETOOLONG; - DBUG_RETURN(1); - /* purecov: end */ - } - table_name= filename + dirlen; - dirlen--; /* Strip off trailing '/'. */ - memcpy(dir_path, filename, dirlen); - dir_path[dirlen]= '\0'; - db= base_name(dir_path); - dirlen-= db - dir_path; /* This is now the length of 'db'. */ - DBUG_PRINT("myrg", ("open: '%s'.'%s'", db, table_name)); - - ha_myrg= (ha_myisammrg*) callback_param; - parent= ha_myrg->table_ptr(); - /* Get a TABLE_LIST object. */ if (!(child_l= (TABLE_LIST*) alloc_root(&parent->mem_root, sizeof(TABLE_LIST)))) @@ -255,13 +233,69 @@ static int myisammrg_parent_open_callback(void *callback_param, } bzero((char*) child_l, sizeof(TABLE_LIST)); - /* Set database (schema) name. */ - child_l->db_length= dirlen; - child_l->db= strmake_root(&parent->mem_root, db, dirlen); - /* Set table name. */ - child_l->table_name_length= strlen(table_name); - child_l->table_name= strmake_root(&parent->mem_root, table_name, - child_l->table_name_length); + /* + Depending on MySQL version, filename may be encoded by table name to + file name encoding or not. Always encoded if parent table is created + by 5.1.46+. Encoded if parent is created by 5.1.6+ and child table is + in different database. + */ + if (!has_path(filename)) + { + /* Child is in the same database as parent. */ + child_l->db_length= parent->s->db.length; + child_l->db= strmake_root(&parent->mem_root, parent->s->db.str, + child_l->db_length); + /* Child table name is encoded in parent dot-MRG starting with 5.1.46. */ + if (parent->s->mysql_version >= 50146) + { + child_l->table_name_length= filename_to_tablename(filename, name_buf, + sizeof(name_buf)); + child_l->table_name= strmake_root(&parent->mem_root, name_buf, + child_l->table_name_length); + } + else + { + child_l->table_name_length= strlen(filename); + child_l->table_name= strmake_root(&parent->mem_root, filename, + child_l->table_name_length); + } + } + else + { + DBUG_ASSERT(strlen(filename) < sizeof(dir_path)); + fn_format(dir_path, filename, "", "", 0); + /* Extract child table name and database name from filename. */ + dirlen= dirname_length(dir_path); + /* Child db/table name is encoded in parent dot-MRG starting with 5.1.6. */ + if (parent->s->mysql_version >= 50106) + { + child_l->table_name_length= filename_to_tablename(dir_path + dirlen, + name_buf, + sizeof(name_buf)); + child_l->table_name= strmake_root(&parent->mem_root, name_buf, + child_l->table_name_length); + dir_path[dirlen - 1]= 0; + dirlen= dirname_length(dir_path); + child_l->db_length= filename_to_tablename(dir_path + dirlen, name_buf, + sizeof(name_buf)); + child_l->db= strmake_root(&parent->mem_root, name_buf, child_l->db_length); + } + else + { + child_l->table_name_length= strlen(dir_path + dirlen); + child_l->table_name= strmake_root(&parent->mem_root, dir_path + dirlen, + child_l->table_name_length); + dir_path[dirlen - 1]= 0; + dirlen= dirname_length(dir_path); + child_l->db_length= strlen(dir_path + dirlen); + child_l->db= strmake_root(&parent->mem_root, dir_path + dirlen, + child_l->db_length); + } + } + + DBUG_PRINT("myrg", ("open: '%.*s'.'%.*s'", child_l->db_length, child_l->db, + child_l->table_name_length, child_l->table_name)); + /* Convert to lowercase if required. */ if (lower_case_table_names && child_l->table_name_length) child_l->table_name_length= my_casedn_str(files_charset_info, @@ -1132,7 +1166,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form, /* Create child path names. */ for (pos= table_names; tables; tables= tables->next_local) { - const char *table_name; + const char *table_name= buff; /* Construct the path to the MyISAM table. Try to meet two conditions: @@ -1158,10 +1192,12 @@ int ha_myisammrg::create(const char *name, register TABLE *form, as the MyISAM tables are from the same database as the MERGE table. */ if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt)) - table_name= tables->table_name; - else - if (! (table_name= thd->strmake(buff, length))) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */ + { + table_name+= dirlgt; + length-= dirlgt; + } + if (!(table_name= thd->strmake(table_name, length))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */ *pos++= table_name; } @@ -1182,7 +1218,7 @@ void ha_myisammrg::append_create_info(String *packet) const char *current_db; size_t db_length; THD *thd= current_thd; - MYRG_TABLE *open_table, *first; + TABLE_LIST *open_table, *first; if (file->merge_insert_method != MERGE_INSERT_DISABLED) { @@ -1200,14 +1236,11 @@ void ha_myisammrg::append_create_info(String *packet) current_db= table->s->db.str; db_length= table->s->db.length; - for (first=open_table=file->open_tables ; - open_table != file->end_table ; - open_table++) + for (first= open_table= table->child_l;; + open_table= open_table->next_global) { - LEX_STRING db, name; - LINT_INIT(db.str); + LEX_STRING db= { open_table->db, open_table->db_length }; - split_file_name(open_table->table->filename, &db, &name); if (open_table != first) packet->append(','); /* Report database for mapped table if it isn't in current database */ @@ -1218,7 +1251,10 @@ void ha_myisammrg::append_create_info(String *packet) append_identifier(thd, packet, db.str, db.length); packet->append('.'); } - append_identifier(thd, packet, name.str, name.length); + append_identifier(thd, packet, open_table->table_name, + open_table->table_name_length); + if (&open_table->next_global == table->child_last_l) + break; } packet->append(')'); } diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c index 7b310dc2eed..5fcbe0c3297 100644 --- a/storage/myisammrg/myrg_open.c +++ b/storage/myisammrg/myrg_open.c @@ -311,14 +311,6 @@ MYRG_INFO *myrg_parent_open(const char *parent_name, if (!child_name_buff[0] || (child_name_buff[0] == '#')) continue; - if (!has_path(child_name_buff)) - { - VOID(strmake(parent_name_buff + dir_length, child_name_buff, - sizeof(parent_name_buff) - 1 - dir_length)); - VOID(cleanup_dirname(child_name_buff, parent_name_buff)); - } - else - fn_format(child_name_buff, child_name_buff, "", "", 0); DBUG_PRINT("info", ("child: '%s'", child_name_buff)); /* Callback registers child with handler table. */ |