From df9e9f25313d3206c9291a90ac379e45d41e3afa Mon Sep 17 00:00:00 2001 From: "acurtis/antony@xiphis.org/ltantony.xiphis.org" <> Date: Thu, 20 Jul 2006 12:54:01 -0700 Subject: [PATCH 1/9] Bug#19939 AUTHORS and CONTRIBUTORS are not reserved keywords. --- mysql-test/r/keywords.result | 16 ++++++++++++++++ mysql-test/t/keywords.test | 24 ++++++++++++++++++++++++ sql/sql_yacc.yy | 3 ++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result index 88a0ab8abd5..597983dab7e 100644 --- a/mysql-test/r/keywords.result +++ b/mysql-test/r/keywords.result @@ -16,3 +16,19 @@ select events.binlog from events; binlog 1 drop table events; +create procedure p1() +begin +declare n int default 2; +authors: while n > 0 do +set n = n -1; +end while authors; +end| +create procedure p2() +begin +declare n int default 2; +contributors: while n > 0 do +set n = n -1; +end while contributors; +end| +drop procedure p1; +drop procedure p2; diff --git a/mysql-test/t/keywords.test b/mysql-test/t/keywords.test index de0159a950e..1af4a1354be 100644 --- a/mysql-test/t/keywords.test +++ b/mysql-test/t/keywords.test @@ -19,3 +19,27 @@ select events.binlog from events; drop table events; # End of 4.1 tests + +# +# Bug#19939 "AUTHORS is not a keyword" +# +delimiter |; +create procedure p1() +begin + declare n int default 2; + authors: while n > 0 do + set n = n -1; + end while authors; +end| +create procedure p2() +begin + declare n int default 2; + contributors: while n > 0 do + set n = n -1; + end while contributors; +end| +delimiter ;| +drop procedure p1; +drop procedure p2; + +# End of 5.1 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e345b61e41e..d957f94a43d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9339,7 +9339,6 @@ user: keyword: keyword_sp {} | ASCII_SYM {} - | AUTHORS_SYM {} | BACKUP_SYM {} | BEGIN_SYM {} | BYTE_SYM {} @@ -9397,6 +9396,7 @@ keyword_sp: | ALGORITHM_SYM {} | ANY_SYM {} | AT_SYM {} + | AUTHORS_SYM {} | AUTO_INC {} | AUTOEXTEND_SIZE_SYM {} | AVG_ROW_LENGTH {} @@ -9422,6 +9422,7 @@ keyword_sp: | COMPRESSED_SYM {} | CONCURRENT {} | CONSISTENT_SYM {} + | CONTRIBUTORS_SYM {} | CUBE_SYM {} | DATA_SYM {} | DATAFILE_SYM {} From d781552a1894bd2101f5d60d138056efe971cd7e Mon Sep 17 00:00:00 2001 From: "ingo/mydev@chilla.local" <> Date: Fri, 21 Jul 2006 12:22:41 +0200 Subject: [PATCH 2/9] Bug#20719 - Reading dynamic records with write buffer could fail Fixed a possible problem with reading of dynamic records when a write cache is active. The cache must be flushed whenever a part of the file in the write cache is to be read. Added a read optimization to _mi_read_dynamic_record(). No test case. This was a hypothetical but existing problem. --- myisam/mi_dynrec.c | 157 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 129 insertions(+), 28 deletions(-) diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 0ffab05b6bc..c4865315283 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1095,12 +1095,41 @@ void _my_store_blob_length(byte *pos,uint pack_length,uint length) } - /* Read record from datafile */ - /* Returns 0 if ok, -1 if error */ +/* + Read record from datafile. + + SYNOPSIS + _mi_read_dynamic_record() + info MI_INFO pointer to table. + filepos From where to read the record. + buf Destination for record. + + NOTE + + If a write buffer is active, it needs to be flushed if its contents + intersects with the record to read. We always check if the position + of the first byte of the write buffer is lower than the position + past the last byte to read. In theory this is also true if the write + buffer is completely below the read segment. That is, if there is no + intersection. But this case is unusual. We flush anyway. Only if the + first byte in the write buffer is above the last byte to read, we do + not flush. + + A dynamic record may need several reads. So this check must be done + before every read. Reading a dynamic record starts with reading the + block header. If the record does not fit into the free space of the + header, the block may be longer than the header. In this case a + second read is necessary. These one or two reads repeat for every + part of the record. + + RETURN + 0 OK + -1 Error +*/ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) { - int flag; + int block_of_record; uint b_type,left_length; byte *to; MI_BLOCK_INFO block_info; @@ -1112,17 +1141,16 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) LINT_INIT(to); LINT_INIT(left_length); file=info->dfile; - block_info.next_filepos=filepos; /* for easyer loop */ - flag=block_info.second_read=0; + block_of_record= 0; /* First block of record is numbered as zero. */ + block_info.second_read= 0; do { if (info->opt_flag & WRITE_CACHE_USED && - info->rec_cache.pos_in_file <= block_info.next_filepos && + info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH && flush_io_cache(&info->rec_cache)) goto err; info->rec_cache.seek_not_done=1; - if ((b_type=_mi_get_block_info(&block_info,file, - block_info.next_filepos)) + if ((b_type= _mi_get_block_info(&block_info, file, filepos)) & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | BLOCK_FATAL_ERROR)) { @@ -1130,9 +1158,8 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) my_errno=HA_ERR_RECORD_DELETED; goto err; } - if (flag == 0) /* First block */ + if (block_of_record++ == 0) /* First block */ { - flag=1; if (block_info.rec_len > (uint) info->s->base.max_pack_length) goto panic; if (info->s->base.blobs) @@ -1147,11 +1174,35 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) } if (left_length < block_info.data_len || ! block_info.data_len) goto panic; /* Wrong linked record */ - if (my_pread(file,(byte*) to,block_info.data_len,block_info.filepos, - MYF(MY_NABP))) - goto panic; - left_length-=block_info.data_len; - to+=block_info.data_len; + /* copy information that is already read */ + { + uint offset= (uint) (block_info.filepos - filepos); + uint prefetch_len= (sizeof(block_info.header) - offset); + filepos+= sizeof(block_info.header); + + if (prefetch_len > block_info.data_len) + prefetch_len= block_info.data_len; + if (prefetch_len) + { + memcpy((byte*) to, block_info.header + offset, prefetch_len); + block_info.data_len-= prefetch_len; + left_length-= prefetch_len; + to+= prefetch_len; + } + } + /* read rest of record from file */ + if (block_info.data_len) + { + if (info->opt_flag & WRITE_CACHE_USED && + info->rec_cache.pos_in_file < filepos + block_info.data_len && + flush_io_cache(&info->rec_cache)) + goto err; + if (my_read(file, (byte*) to, block_info.data_len, MYF(MY_NABP))) + goto panic; + left_length-=block_info.data_len; + to+=block_info.data_len; + } + filepos= block_info.next_filepos; } while (left_length); info->update|= HA_STATE_AKTIV; /* We have a aktive record */ @@ -1308,11 +1359,45 @@ err: } +/* + Read record from datafile. + + SYNOPSIS + _mi_read_rnd_dynamic_record() + info MI_INFO pointer to table. + buf Destination for record. + filepos From where to read the record. + skip_deleted_blocks If to repeat reading until a non-deleted + record is found. + + NOTE + + If a write buffer is active, it needs to be flushed if its contents + intersects with the record to read. We always check if the position + of the first byte of the write buffer is lower than the position + past the last byte to read. In theory this is also true if the write + buffer is completely below the read segment. That is, if there is no + intersection. But this case is unusual. We flush anyway. Only if the + first byte in the write buffer is above the last byte to read, we do + not flush. + + A dynamic record may need several reads. So this check must be done + before every read. Reading a dynamic record starts with reading the + block header. If the record does not fit into the free space of the + header, the block may be longer than the header. In this case a + second read is necessary. These one or two reads repeat for every + part of the record. + + RETURN + 0 OK + != 0 Error +*/ + int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, register my_off_t filepos, - my_bool skipp_deleted_blocks) + my_bool skip_deleted_blocks) { - int flag,info_read,save_errno; + int block_of_record, info_read, save_errno; uint left_len,b_type; byte *to; MI_BLOCK_INFO block_info; @@ -1338,7 +1423,8 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, else info_read=1; /* memory-keyinfoblock is ok */ - flag=block_info.second_read=0; + block_of_record= 0; /* First block of record is numbered as zero. */ + block_info.second_read= 0; left_len=1; do { @@ -1361,15 +1447,15 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, { if (_mi_read_cache(&info->rec_cache,(byte*) block_info.header,filepos, sizeof(block_info.header), - (!flag && skipp_deleted_blocks ? READING_NEXT : 0) | - READING_HEADER)) + (!block_of_record && skip_deleted_blocks ? + READING_NEXT : 0) | READING_HEADER)) goto panic; b_type=_mi_get_block_info(&block_info,-1,filepos); } else { if (info->opt_flag & WRITE_CACHE_USED && - info->rec_cache.pos_in_file <= filepos && + info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH && flush_io_cache(&info->rec_cache)) DBUG_RETURN(my_errno); info->rec_cache.seek_not_done=1; @@ -1380,7 +1466,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, BLOCK_FATAL_ERROR)) { if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR)) - && skipp_deleted_blocks) + && skip_deleted_blocks) { filepos=block_info.filepos+block_info.block_len; block_info.second_read=0; @@ -1394,7 +1480,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, } goto err; } - if (flag == 0) /* First block */ + if (block_of_record == 0) /* First block */ { if (block_info.rec_len > (uint) share->base.max_pack_length) goto panic; @@ -1427,7 +1513,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, left_len-=tmp_length; to+=tmp_length; filepos+=tmp_length; - } + } } /* read rest of record from file */ if (block_info.data_len) @@ -1436,11 +1522,17 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, { if (_mi_read_cache(&info->rec_cache,(byte*) to,filepos, block_info.data_len, - (!flag && skipp_deleted_blocks) ? READING_NEXT :0)) + (!block_of_record && skip_deleted_blocks) ? + READING_NEXT : 0)) goto panic; } else { + if (info->opt_flag & WRITE_CACHE_USED && + info->rec_cache.pos_in_file < + block_info.filepos + block_info.data_len && + flush_io_cache(&info->rec_cache)) + goto err; /* VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0))); */ if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP))) { @@ -1450,10 +1542,14 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, } } } - if (flag++ == 0) + /* + Increment block-of-record counter. If it was the first block, + remember the position behind the block for the next call. + */ + if (block_of_record++ == 0) { - info->nextpos=block_info.filepos+block_info.block_len; - skipp_deleted_blocks=0; + info->nextpos= block_info.filepos + block_info.block_len; + skip_deleted_blocks= 0; } left_len-=block_info.data_len; to+=block_info.data_len; @@ -1485,6 +1581,11 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos) if (file >= 0) { + /* + We do not use my_pread() here because we want to have the file + pointer set to the end of the header after this function. + my_pread() may leave the file pointer untouched. + */ VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); if (my_read(file,(char*) header,sizeof(info->header),MYF(0)) != sizeof(info->header)) From b4a7c01771c6ddd719c15a955288b2031fbbde48 Mon Sep 17 00:00:00 2001 From: "pgalbraith/patg@buffy.netfrastructure.com" <> Date: Thu, 27 Jul 2006 14:02:58 -0400 Subject: [PATCH 3/9] BUG #21118 "Federated Transaction test needs to have BDB switched to InnoDB" Changed federated_transactions.test to use InnoDB instead of BDB federated_transactions-slave.opt: BitKeeper file /home/patg/mysql-build/mysql-5.1-engines-bug21118/mysql-test/t/federated_transactions-slave.opt federated_transactions.result: BUG #21118 "Federated Transaction test needs to have BDB switched to InnoDB" New test results for InnoDB being remote transactional table federated_transactions.test: BUG #21118 "Federated Transaction test needs to have BDB switched to InnoDB" Changed remote transactional table from BDB to InnoDB --- mysql-test/r/federated_transactions.result | 2 +- mysql-test/t/federated_transactions-slave.opt | 1 + mysql-test/t/federated_transactions.test | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 mysql-test/t/federated_transactions-slave.opt diff --git a/mysql-test/r/federated_transactions.result b/mysql-test/r/federated_transactions.result index 403b65b5484..e6714210ded 100644 --- a/mysql-test/r/federated_transactions.result +++ b/mysql-test/r/federated_transactions.result @@ -16,7 +16,7 @@ CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `name` varchar(32) NOT NULL default '' ) -DEFAULT CHARSET=latin1 ENGINE=BerkeleyDB; +DEFAULT CHARSET=latin1 ENGINE=InnoDB; DROP TABLE IF EXISTS federated.t1; Warnings: Note 1051 Unknown table 't1' diff --git a/mysql-test/t/federated_transactions-slave.opt b/mysql-test/t/federated_transactions-slave.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/t/federated_transactions-slave.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/t/federated_transactions.test b/mysql-test/t/federated_transactions.test index 5095c8ce9c3..128813ed160 100644 --- a/mysql-test/t/federated_transactions.test +++ b/mysql-test/t/federated_transactions.test @@ -1,6 +1,6 @@ # should work with embedded server after mysqltest is fixed -- source include/not_embedded.inc -source include/have_bdb.inc; +#source include/have_innodb.inc; source include/federated.inc; connection slave; @@ -10,7 +10,7 @@ CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `name` varchar(32) NOT NULL default '' ) - DEFAULT CHARSET=latin1 ENGINE=BerkeleyDB; + DEFAULT CHARSET=latin1 ENGINE=InnoDB; connection master; DROP TABLE IF EXISTS federated.t1; From e1723f7384e1bf42b8bd5051f5d206efab8d78f0 Mon Sep 17 00:00:00 2001 From: "pgalbraith/patg@buffy.netfrastructure.com" <> Date: Thu, 27 Jul 2006 14:20:25 -0400 Subject: [PATCH 4/9] BUG #21118 "Federated Transaction test needs to have BDB switched to InnoDB" recommented the uncommented have_innodb.inc line federated_transactions.test: BUG #21118 "Federated Transaction test needs to have BDB switched to InnoDB" slight ommission fixed --- mysql-test/t/federated_transactions.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/federated_transactions.test b/mysql-test/t/federated_transactions.test index 128813ed160..9f3b030f462 100644 --- a/mysql-test/t/federated_transactions.test +++ b/mysql-test/t/federated_transactions.test @@ -1,6 +1,6 @@ # should work with embedded server after mysqltest is fixed -- source include/not_embedded.inc -#source include/have_innodb.inc; +source include/have_innodb.inc; source include/federated.inc; connection slave; From eddb73b3653334d925643e588802cbe86dcd27a5 Mon Sep 17 00:00:00 2001 From: "ingo/mydev@chilla.local" <> Date: Sat, 29 Jul 2006 21:58:50 +0200 Subject: [PATCH 5/9] Bug#20719 - Reading dynamic records with write buffer could fail After merge fix --- myisam/mi_dynrec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 51f2ff349f8..4dec3055fa1 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1141,6 +1141,9 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) block_info.second_read= 0; do { + /* A corrupted table can have wrong pointers. (Bug# 19835) */ + if (filepos == HA_OFFSET_ERROR) + goto panic; if (info->opt_flag & WRITE_CACHE_USED && info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH && flush_io_cache(&info->rec_cache)) From 1962eaaf62c077f84d24eb86d3fd978c04ef83cd Mon Sep 17 00:00:00 2001 From: "ingo/mydev@chilla.local" <> Date: Sun, 30 Jul 2006 06:19:30 +0200 Subject: [PATCH 6/9] Bug#20719 - Reading dynamic records with write buffer could fail After merge fix --- myisam/mi_dynrec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index f834cc5a724..ef5ab73f1a9 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1187,9 +1187,6 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH && flush_io_cache(&info->rec_cache)) goto err; - /* A corrupted table can have wrong pointers. (Bug# 19835) */ - if (block_info.next_filepos == HA_OFFSET_ERROR) - goto panic; info->rec_cache.seek_not_done=1; if ((b_type= _mi_get_block_info(&block_info, file, filepos)) & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | From 8e4c36ad4afa35b07b15f3ebbcd51007e925125c Mon Sep 17 00:00:00 2001 From: "ingo/istruewing@chilla.local" <> Date: Wed, 2 Aug 2006 17:57:06 +0200 Subject: [PATCH 7/9] Bug#18775 - Temporary table from alter table visible to other threads Continued implementation of WL#1324 (table name to filename encoding) The intermediate (not temporary) files of the new table during ALTER TABLE was visible for SHOW TABLES. These intermediate files are copies of the original table with the changes done by ALTER TABLE. After all the data is copied over from the original table, these files are renamed to the original tables file names. So they are not temporary files. They persist after ALTER TABLE, but just with another name. In 5.0 the intermediate files are invisible for SHOW TABLES because all file names beginning with "#sql" were suppressed. This failed since 5.1.6 because even temporary table names were converted when making file names from them. The prefix became converted to "@0023sql". Converting the prefix during SHOW TABLES would suppress the listing of user tables that start with "#sql". The solution of the problem is to continue the implementation of the table name to file name conversion feature. One requirement is to suppress the conversion for temporary table names. This change is straightforward for real temporary tables as there is a function that creates temporary file names. But the generated path names are located in TMPDIR and have no relation to the internal table name. This cannot be used for ALTER TABLE. Its intermediate files need to be in the same directory as the old table files. And it is necessary to be able to deduce the same path from the same table name repeatedly. Consequently the intermediate table files must be handled like normal tables. Their internal names shall start with tmp_file_prefix (#sql) and they shall not be converted like normal table names. I added a flags parameter to all relevant functions that are called from ALTER TABLE. It is used to suppress the conversion for the intermediate table files. The outcome is that the suppression of #sql in SHOW TABLES works again. It does not suppress user tables as these are converted to @0023sql on file level. This patch does also fix ALTER TABLE ... RENAME, which could not rename a table with non-ASCII characters in its name. It does also fix the problem that a user could create a table like `#sql-xxxx-yyyy`, where xxxx is mysqld's pid and yyyy is the thread ID of some other thread, which prevented this thread from running ALTER TABLE. Some of the above problems are mentioned in Bug 1405, which can be closed with this patch. This patch does also contain some minor fixes for other forgotten conversions. Still known problems are reported as bugs 21370, 21373, and 21387. --- mysql-test/r/alter_table.result | 60 +++++++ mysql-test/r/backup.result | 20 +++ mysql-test/r/repair.result | 6 + mysql-test/t/alter_table.test | 63 +++++++ mysql-test/t/backup.test | 19 ++ mysql-test/t/repair.test | 13 ++ sql/ha_myisam.cc | 10 +- sql/ha_myisammrg.cc | 2 +- sql/ha_ndbcluster.cc | 14 +- sql/ha_ndbcluster_binlog.cc | 13 +- sql/ha_ndbcluster_binlog.h | 2 +- sql/mysql_priv.h | 17 +- sql/sql_acl.cc | 2 +- sql/sql_base.cc | 13 +- sql/sql_db.cc | 22 +-- sql/sql_delete.cc | 2 +- sql/sql_insert.cc | 8 +- sql/sql_partition.cc | 26 +-- sql/sql_rename.cc | 8 +- sql/sql_show.cc | 11 +- sql/sql_table.cc | 292 +++++++++++++++++++++++-------- sql/sql_trigger.cc | 17 +- sql/sql_view.cc | 6 +- sql/table.cc | 13 +- storage/innobase/row/row0mysql.c | 4 +- 25 files changed, 503 insertions(+), 160 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index f4332ea9888..3095d5337ed 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -657,3 +657,63 @@ SELECT * FROM t1; v b abc 5 DROP TABLE t1; +DROP DATABASE IF EXISTS mysqltest; +CREATE DATABASE mysqltest; +use mysqltest; +DROP TABLE IF EXISTS `t1_nägel`, `t1_blüten`; +CREATE TABLE `t1_nägel` (c1 INT); +ALTER TABLE `t1_nägel` RENAME `t1_blüten`; +CREATE TABLE `t1_nägel` (c1 INT); +ALTER TABLE `t1_nägel` RENAME `t1_blüten`; +ERROR 42S01: Table 't1_blЭten' already exists +DROP TABLE `t1_nägel`, `t1_blüten`; +CREATE TEMPORARY TABLE `tt1_nägel` (c1 INT); +ALTER TABLE `tt1_nägel` RENAME `tt1_blüten`; +CREATE TEMPORARY TABLE `tt1_nägel` (c1 INT); +ALTER TABLE `tt1_nägel` RENAME `tt1_blüten`; +ERROR 42S01: Table 'tt1_blЭten' already exists +SHOW CREATE TABLE `tt1_blüten`; +Table Create Table +tt1_blüten CREATE TEMPORARY TABLE `tt1_blüten` ( + `c1` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE `tt1_nägel`, `tt1_blüten`; +CREATE TABLE `#sql1` (c1 INT); +CREATE TABLE `@0023sql2` (c1 INT); +SHOW TABLES; +Tables_in_mysqltest +#sql1 +@0023sql2 +RENAME TABLE `#sql1` TO `@0023sql1`; +RENAME TABLE `@0023sql2` TO `#sql2`; +SHOW TABLES; +Tables_in_mysqltest +#sql2 +@0023sql1 +ALTER TABLE `@0023sql1` RENAME `#sql-1`; +ALTER TABLE `#sql2` RENAME `@0023sql-2`; +SHOW TABLES; +Tables_in_mysqltest +#sql-1 +@0023sql-2 +INSERT INTO `#sql-1` VALUES (1); +INSERT INTO `@0023sql-2` VALUES (2); +DROP TABLE `#sql-1`, `@0023sql-2`; +CREATE TEMPORARY TABLE `#sql1` (c1 INT); +CREATE TEMPORARY TABLE `@0023sql2` (c1 INT); +SHOW TABLES; +Tables_in_mysqltest +ALTER TABLE `#sql1` RENAME `@0023sql1`; +ALTER TABLE `@0023sql2` RENAME `#sql2`; +SHOW TABLES; +Tables_in_mysqltest +INSERT INTO `#sql2` VALUES (1); +INSERT INTO `@0023sql1` VALUES (2); +SHOW CREATE TABLE `@0023sql1`; +Table Create Table +@0023sql1 CREATE TEMPORARY TABLE `@0023sql1` ( + `c1` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE `#sql2`, `@0023sql1`; +use test; +DROP DATABASE mysqltest; diff --git a/mysql-test/r/backup.result b/mysql-test/r/backup.result index a65808bbdd6..05761240ca7 100644 --- a/mysql-test/r/backup.result +++ b/mysql-test/r/backup.result @@ -101,3 +101,23 @@ test.t5 backup status OK Warnings: Warning 1541 The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead. drop table t5; +DROP TABLE IF EXISTS `t-blüten`; +CREATE TABLE `t-blüten` (c1 INT); +INSERT INTO `t-blüten` VALUES (1), (2), (3); +BACKUP TABLE `t-blüten` TO '../tmp'; +Table Op Msg_type Msg_text +test.t-blüten backup status OK +Warnings: +Warning 1541 The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead. +DROP TABLE `t-blüten`; +RESTORE TABLE `t-blüten` FROM '../tmp'; +Table Op Msg_type Msg_text +test.t-blüten restore status OK +Warnings: +Warning 1541 The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead. +SELECT * FROM `t-blüten`; +c1 +1 +2 +3 +DROP TABLE `t-blüten`; diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index d8fa4dbbb72..f08dc6a8a4a 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -41,3 +41,9 @@ Table Op Msg_type Msg_text test.t1 repair warning Number of rows changed from 0 to 1 test.t1 repair status OK drop table t1; +DROP TABLE IF EXISTS tt1; +CREATE TEMPORARY TABLE tt1 (c1 INT); +REPAIR TABLE tt1 USE_FRM; +Table Op Msg_type Msg_text +tt1 repair error Cannot repair temporary table from .frm file +DROP TABLE tt1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index efe58579785..f6af92e0044 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -482,3 +482,66 @@ SELECT * FROM t1; ALTER TABLE t1 MODIFY COLUMN v VARCHAR(4); SELECT * FROM t1; DROP TABLE t1; + +# End of 5.0 tests + +# +# Bug#18775 - Temporary table from alter table visible to other threads +# +# Use a special database to avoid name clashes with user tables. +--disable_warnings +DROP DATABASE IF EXISTS mysqltest; +--enable_warnings +CREATE DATABASE mysqltest; +use mysqltest; +# +# Check if non-ASCII alphabetic characters work and duplicates are detected. +--disable_warnings +DROP TABLE IF EXISTS `t1_nägel`, `t1_blüten`; +--enable_warnings +CREATE TABLE `t1_nägel` (c1 INT); +ALTER TABLE `t1_nägel` RENAME `t1_blüten`; +CREATE TABLE `t1_nägel` (c1 INT); +--error ER_TABLE_EXISTS_ERROR +ALTER TABLE `t1_nägel` RENAME `t1_blüten`; +DROP TABLE `t1_nägel`, `t1_blüten`; +# +# Same for temporary tables though these names do not become file names. +CREATE TEMPORARY TABLE `tt1_nägel` (c1 INT); +ALTER TABLE `tt1_nägel` RENAME `tt1_blüten`; +CREATE TEMPORARY TABLE `tt1_nägel` (c1 INT); +--error ER_TABLE_EXISTS_ERROR +ALTER TABLE `tt1_nägel` RENAME `tt1_blüten`; +SHOW CREATE TABLE `tt1_blüten`; +DROP TABLE `tt1_nägel`, `tt1_blüten`; +# +# Check if special characters as in tmp_file_prefix work. +CREATE TABLE `#sql1` (c1 INT); +CREATE TABLE `@0023sql2` (c1 INT); +SHOW TABLES; +RENAME TABLE `#sql1` TO `@0023sql1`; +RENAME TABLE `@0023sql2` TO `#sql2`; +SHOW TABLES; +ALTER TABLE `@0023sql1` RENAME `#sql-1`; +ALTER TABLE `#sql2` RENAME `@0023sql-2`; +SHOW TABLES; +INSERT INTO `#sql-1` VALUES (1); +INSERT INTO `@0023sql-2` VALUES (2); +DROP TABLE `#sql-1`, `@0023sql-2`; +# +# Same for temporary tables though these names do not become file names. +CREATE TEMPORARY TABLE `#sql1` (c1 INT); +CREATE TEMPORARY TABLE `@0023sql2` (c1 INT); +SHOW TABLES; +ALTER TABLE `#sql1` RENAME `@0023sql1`; +ALTER TABLE `@0023sql2` RENAME `#sql2`; +SHOW TABLES; +INSERT INTO `#sql2` VALUES (1); +INSERT INTO `@0023sql1` VALUES (2); +SHOW CREATE TABLE `@0023sql1`; +DROP TABLE `#sql2`, `@0023sql1`; +# +# Cleanup +use test; +DROP DATABASE mysqltest; + diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test index 917c3f98ebb..fa6bbc21813 100644 --- a/mysql-test/t/backup.test +++ b/mysql-test/t/backup.test @@ -58,3 +58,22 @@ drop table t5; --system rm $MYSQLTEST_VARDIR/tmp/t?.* # End of 4.1 tests +# End of 5.0 tests + +# +# Bug#18775 - Temporary table from alter table visible to other threads +# +# Backup did not encode table names. +--disable_warnings +DROP TABLE IF EXISTS `t-blüten`; +--enable_warnings +CREATE TABLE `t-blüten` (c1 INT); +INSERT INTO `t-blüten` VALUES (1), (2), (3); +BACKUP TABLE `t-blüten` TO '../tmp'; +DROP TABLE `t-blüten`; +# +# Same for restore. +RESTORE TABLE `t-blüten` FROM '../tmp'; +SELECT * FROM `t-blüten`; +DROP TABLE `t-blüten`; + diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index 16e1d76d460..c79768dbb46 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -35,3 +35,16 @@ repair table t1 use_frm; drop table t1; # End of 4.1 tests +# End of 5.0 tests + +# +# Bug#18775 - Temporary table from alter table visible to other threads +# +# REPAIR TABLE ... USE_FRM on temporary table crashed the table or server. +--disable_warnings +DROP TABLE IF EXISTS tt1; +--enable_warnings +CREATE TEMPORARY TABLE tt1 (c1 INT); +REPAIR TABLE tt1 USE_FRM; +DROP TABLE tt1; + diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 2d097c34f97..55b39f46c19 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -464,11 +464,14 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) HA_CHECK_OPT tmp_check_opt; char *backup_dir= thd->lex->backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; - const char *table_name= table->s->table_name.str; + char table_name[FN_REFLEN]; int error; const char* errmsg; DBUG_ENTER("restore"); + VOID(tablename_to_filename(table->s->table_name.str, table_name, + sizeof(table_name))); + if (fn_format_relative_to_data_home(src_path, table_name, backup_dir, MI_NAME_DEXT)) DBUG_RETURN(HA_ADMIN_INVALID); @@ -504,11 +507,14 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) { char *backup_dir= thd->lex->backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; - const char *table_name= table->s->table_name.str; + char table_name[FN_REFLEN]; int error; const char *errmsg; DBUG_ENTER("ha_myisam::backup"); + VOID(tablename_to_filename(table->s->table_name.str, table_name, + sizeof(table_name))); + if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir, reg_ext)) { diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index afeed5f79df..5afabffcefe 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -473,7 +473,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form, an embedded server without changing the paths in the .MRG file. */ uint length= build_table_filename(buff, sizeof(buff), - tables->db, tables->table_name, ""); + tables->db, tables->table_name, "", 0); /* If a MyISAM table is in the same directory as the MERGE table, we use the table name without a path. This means that the diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 8b17dae9d7e..47c877ccf4d 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -5795,7 +5795,7 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name, DBUG_RETURN(HA_ERR_NO_CONNECTION); ndb->setDatabaseName(db); NDBDICT* dict= ndb->getDictionary(); - build_table_filename(key, sizeof(key), db, name, ""); + build_table_filename(key, sizeof(key), db, name, "", 0); NDB_SHARE *share= get_share(key, 0, false); if (share && get_ndb_share_state(share) == NSS_ALTERED) { @@ -5938,7 +5938,7 @@ int ndbcluster_drop_database_impl(const char *path) // Drop any tables belonging to database char full_path[FN_REFLEN]; char *tmp= full_path + - build_table_filename(full_path, sizeof(full_path), dbname, "", ""); + build_table_filename(full_path, sizeof(full_path), dbname, "", "", 0); ndb->setDatabaseName(dbname); List_iterator_fast it(drop_list); @@ -6061,7 +6061,7 @@ int ndbcluster_find_all_files(THD *thd) /* check if database exists */ char *end= key + - build_table_filename(key, sizeof(key), elmt.database, "", ""); + build_table_filename(key, sizeof(key), elmt.database, "", "", 0); if (my_access(key, F_OK)) { /* no such database defined, skip table */ @@ -6204,7 +6204,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path, } // File is not in NDB, check for .ndb file with this name - build_table_filename(name, sizeof(name), db, file_name, ha_ndb_ext); + build_table_filename(name, sizeof(name), db, file_name, ha_ndb_ext, 0); DBUG_PRINT("info", ("Check access for %s", name)); if (my_access(name, F_OK)) { @@ -6229,7 +6229,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path, /* setup logging to binlog for all discovered tables */ { char *end, *end1= name + - build_table_filename(name, sizeof(name), db, "", ""); + build_table_filename(name, sizeof(name), db, "", "", 0); for (i= 0; i < ok_tables.records; i++) { file_name= (char*)hash_element(&ok_tables, i); @@ -6251,7 +6251,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path, file_name= hash_element(&ndb_tables, i); if (!hash_search(&ok_tables, file_name, strlen(file_name))) { - build_table_filename(name, sizeof(name), db, file_name, reg_ext); + build_table_filename(name, sizeof(name), db, file_name, reg_ext, 0); if (my_access(name, F_OK)) { DBUG_PRINT("info", ("%s must be discovered", file_name)); @@ -6802,7 +6802,7 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, NDB_SHARE *share; DBUG_ENTER("ndb_get_commitcount"); - build_table_filename(name, sizeof(name), dbname, tabname, ""); + build_table_filename(name, sizeof(name), dbname, tabname, "", 0); DBUG_PRINT("enter", ("name: %s", name)); pthread_mutex_lock(&ndbcluster_mutex); if (!(share=(NDB_SHARE*) hash_search(&ndbcluster_open_tables, diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 8e9f0077dd0..ee9e639199c 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -737,7 +737,7 @@ static int ndbcluster_create_apply_status_table(THD *thd) */ { build_table_filename(buf, sizeof(buf), - NDB_REP_DB, NDB_APPLY_TABLE, reg_ext); + NDB_REP_DB, NDB_APPLY_TABLE, reg_ext, 0); my_delete(buf, MYF(0)); } @@ -786,7 +786,7 @@ static int ndbcluster_create_schema_table(THD *thd) */ { build_table_filename(buf, sizeof(buf), - NDB_REP_DB, NDB_SCHEMA_TABLE, reg_ext); + NDB_REP_DB, NDB_SCHEMA_TABLE, reg_ext, 0); my_delete(buf, MYF(0)); } @@ -1247,7 +1247,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, NDB_SCHEMA_OBJECT *ndb_schema_object; { char key[FN_REFLEN]; - build_table_filename(key, sizeof(key), db, table_name, ""); + build_table_filename(key, sizeof(key), db, table_name, "", 0); ndb_schema_object= ndb_get_schema_object(key, TRUE, FALSE); } @@ -1577,7 +1577,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, DBUG_PRINT("info", ("Detected frm change of table %s.%s", dbname, tabname)); - build_table_filename(key, FN_LEN-1, dbname, tabname, NullS); + build_table_filename(key, FN_LEN-1, dbname, tabname, NullS, 0); /* If the frm of the altered table is different than the one on disk then overwrite it with the new table definition @@ -1775,7 +1775,8 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, case SOT_TRUNCATE_TABLE: { char key[FN_REFLEN]; - build_table_filename(key, sizeof(key), schema->db, schema->name, ""); + build_table_filename(key, sizeof(key), + schema->db, schema->name, "", 0); NDB_SHARE *share= get_share(key, 0, FALSE, FALSE); // invalidation already handled by binlog thread if (!share || !share->op) @@ -1979,7 +1980,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, { enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type; char key[FN_REFLEN]; - build_table_filename(key, sizeof(key), schema->db, schema->name, ""); + build_table_filename(key, sizeof(key), schema->db, schema->name, "", 0); if (schema_type == SOT_CLEAR_SLOCK) { pthread_mutex_lock(&ndbcluster_mutex); diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h index 58bf7517df5..4c3cd105d1d 100644 --- a/sql/ha_ndbcluster_binlog.h +++ b/sql/ha_ndbcluster_binlog.h @@ -23,7 +23,7 @@ typedef NdbDictionary::Index NDBINDEX; typedef NdbDictionary::Dictionary NDBDICT; typedef NdbDictionary::Event NDBEVENT; -#define IS_TMP_PREFIX(A) (is_prefix(A, tmp_file_prefix) || is_prefix(A, "@0023sql")) +#define IS_TMP_PREFIX(A) (is_prefix(A, tmp_file_prefix)) extern ulong ndb_extra_logging; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7cff7d7531c..c12ec1a9204 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -733,7 +733,7 @@ int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables, bool if_exists, bool drop_temporary, bool log_query); bool quick_rm_table(handlerton *base,const char *db, - const char *table_name); + const char *table_name, uint flags); void close_cached_table(THD *thd, TABLE *table); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent); bool mysql_change_db(THD *thd,const char *name,bool no_access_check); @@ -880,11 +880,9 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok); bool mysql_create_like_table(THD *thd, TABLE_LIST *table, HA_CREATE_INFO *create_info, Table_ident *src_table); -bool mysql_rename_table(handlerton *base, - const char *old_db, - const char * old_name, - const char *new_db, - const char * new_name); +bool mysql_rename_table(handlerton *base, const char *old_db, + const char * old_name, const char *new_db, + const char * new_name, uint flags); bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys); bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info); @@ -1827,7 +1825,12 @@ uint strconvert(CHARSET_INFO *from_cs, const char *from, uint filename_to_tablename(const char *from, char *to, uint to_length); uint tablename_to_filename(const char *from, char *to, uint to_length); uint build_table_filename(char *buff, size_t bufflen, const char *db, - const char *table, const char *ext); + const char *table, const char *ext, uint flags); +/* Flags for conversion functions. */ +#define FN_FROM_IS_TMP (1 << 0) +#define FN_TO_IS_TMP (1 << 1) +#define FN_IS_TMP (FN_FROM_IS_TMP | FN_TO_IS_TMP) + /* from hostname.cc */ struct in_addr; my_string ip_to_hostname(struct in_addr *in,uint *errors); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index deb7fe2d2b8..1c0ec6b4347 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2962,7 +2962,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, { char buf[FN_REFLEN]; build_table_filename(buf, sizeof(buf), table_list->db, - table_list->table_name, reg_ext); + table_list->table_name, reg_ext, 0); fn_format(buf, buf, "", "", MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS | MY_RETURN_REAL_PATH | MY_APPEND_EXT); if (access(buf,F_OK)) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c2ebd140720..f54a8c6ac4a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -252,7 +252,7 @@ uint cached_table_definitions(void) Get TABLE_SHARE for a table. get_table_share() - thd Table share + thd Thread handle table_list Table that should be opened key Table cache key key_length Length of key @@ -1499,15 +1499,18 @@ TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list) char key[MAX_DBKEY_LENGTH]; uint key_length; TABLE *table; + DBUG_ENTER("find_temporary_table"); + DBUG_PRINT("enter", ("table: '%s'.'%s'", + table_list->db, table_list->table_name)); key_length= create_table_def_key(thd, key, table_list, 1); for (table=thd->temporary_tables ; table ; table= table->next) { if (table->s->table_cache_key.length == key_length && !memcmp(table->s->table_cache_key.str, key, key_length)) - return table; + DBUG_RETURN(table); } - return 0; // Not a temporary table + DBUG_RETURN(0); // Not a temporary table } @@ -1948,7 +1951,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, char path[FN_REFLEN]; enum legacy_db_type not_used; build_table_filename(path, sizeof(path) - 1, - table_list->db, table_list->table_name, reg_ext); + table_list->db, table_list->table_name, reg_ext, 0); if (mysql_frm_type(thd, path, ¬_used) == FRMTYPE_VIEW) { /* @@ -3487,6 +3490,8 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, uint key_length; TABLE_LIST table_list; DBUG_ENTER("open_temporary_table"); + DBUG_PRINT("enter", ("table: '%s'.'%s' path: '%s'", + db, table_name, path)); table_list.db= (char*) db; table_list.table_name= (char*) table_name; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 41e7e5df1f7..67d09da3d60 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -560,7 +560,7 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); /* Check directory */ - path_len= build_table_filename(path, sizeof(path), db, "", ""); + path_len= build_table_filename(path, sizeof(path), db, "", "", 0); path[path_len-1]= 0; // Remove last '/' from path if (my_stat(path,&stat_info,MYF(0))) @@ -704,7 +704,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) We pass MY_DB_OPT_FILE as "extension" to avoid "table name to file name" encoding. */ - build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE); + build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE, 0); if ((error=write_db_opt(thd, path, create_info))) goto exit; @@ -797,7 +797,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); - length= build_table_filename(path, sizeof(path), db, "", ""); + length= build_table_filename(path, sizeof(path), db, "", "", 0); strmov(path+length, MY_DB_OPT_FILE); // Append db option file name del_dbopt(path); // Remove dboption hash entry path[length]= '\0'; // Remove file name @@ -1327,7 +1327,7 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) } } #endif - length= build_table_filename(path, sizeof(path), dbname, "", ""); + length= build_table_filename(path, sizeof(path), dbname, "", "", 0); if (length && path[length-1] == FN_LIBCHAR) path[length-1]=0; // remove ending '\' if (my_access(path,F_OK)) @@ -1480,11 +1480,12 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) if (thd->db && !strcmp(thd->db, old_db->str)) change_to_newdb= 1; - build_table_filename(path, sizeof(path)-1, old_db->str, "", MY_DB_OPT_FILE); + build_table_filename(path, sizeof(path)-1, + old_db->str, "", MY_DB_OPT_FILE, 0); if ((load_db_opt(thd, path, &create_info))) create_info.default_table_charset= thd->variables.collation_server; - length= build_table_filename(path, sizeof(path)-1, old_db->str, "", ""); + length= build_table_filename(path, sizeof(path)-1, old_db->str, "", "", 0); if (length && path[length-1] == FN_LIBCHAR) path[length-1]=0; // remove ending '\' if ((error= my_access(path,F_OK))) @@ -1549,9 +1550,10 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) If some tables were left in the new directory, rmdir() will fail. It garantees we never loose any tables. */ - build_table_filename(path, sizeof(path)-1, new_db->str,"",MY_DB_OPT_FILE); + build_table_filename(path, sizeof(path)-1, + new_db->str,"",MY_DB_OPT_FILE, 0); my_delete(path, MYF(MY_WME)); - length= build_table_filename(path, sizeof(path)-1, new_db->str, "", ""); + length= build_table_filename(path, sizeof(path)-1, new_db->str, "", "", 0); if (length && path[length-1] == FN_LIBCHAR) path[length-1]=0; // remove ending '\' rmdir(path); @@ -1603,9 +1605,9 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) /* pass empty file name, and file->name as extension to avoid encoding */ build_table_filename(oldname, sizeof(oldname)-1, - old_db->str, "", file->name); + old_db->str, "", file->name, 0); build_table_filename(newname, sizeof(newname)-1, - new_db->str, "", file->name); + new_db->str, "", file->name, 0); my_rename(oldname, newname, MYF(MY_WME)); } my_dirend(dirp); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index b9ce1a53aaf..25fb6d99d08 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -888,7 +888,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) } path_length= build_table_filename(path, sizeof(path), table_list->db, - table_list->table_name, reg_ext); + table_list->table_name, reg_ext, 0); if (!dont_send_ok) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 1f93bc99483..1a9acd79f6e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2721,7 +2721,8 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ((thd->prelocked_mode == PRELOCKED) ? MYSQL_OPEN_IGNORE_LOCKED_TABLES:0))))) quick_rm_table(create_info->db_type, create_table->db, - table_case_name(create_info, create_table->table_name)); + table_case_name(create_info, create_table->table_name), + 0); } reenable_binlog(thd); if (!table) // open failed @@ -2743,7 +2744,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, hash_delete(&open_cache,(byte*) table); VOID(pthread_mutex_unlock(&LOCK_open)); quick_rm_table(create_info->db_type, create_table->db, - table_case_name(create_info, create_table->table_name)); + table_case_name(create_info, create_table->table_name), 0); DBUG_RETURN(0); } table->file->extra(HA_EXTRA_WRITE_CACHE); @@ -2931,7 +2932,8 @@ void select_create::abort() table->s->version= 0; hash_delete(&open_cache,(byte*) table); if (!create_info->table_existed) - quick_rm_table(table_type, create_table->db, create_table->table_name); + quick_rm_table(table_type, create_table->db, + create_table->table_name, 0); /* Tell threads waiting for refresh that something has happened */ if (version != refresh_version) broadcast_refresh(); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 44c0b8ffcd9..8dcceae72ca 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3430,7 +3430,7 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf, char *src_db= table_ident->db.str ? table_ident->db.str : thd->db; char *src_table= table_ident->table.str; char buf[FN_REFLEN]; - build_table_filename(buf, sizeof(buf), src_db, src_table, ""); + build_table_filename(buf, sizeof(buf), src_db, src_table, "", 0); if (partition_default_handling(table, part_info, FALSE, buf)) { @@ -4704,7 +4704,7 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt) handler *file= lpt->table->file; DBUG_ENTER("mysql_change_partitions"); - build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, ""); + build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "", 0); if ((error= file->change_partitions(lpt->create_info, path, &lpt->copied, &lpt->deleted, lpt->pack_frm_data, lpt->pack_frm_len))) @@ -4744,7 +4744,7 @@ static bool mysql_rename_partitions(ALTER_PARTITION_PARAM_TYPE *lpt) int error; DBUG_ENTER("mysql_rename_partitions"); - build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, ""); + build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "", 0); if ((error= lpt->table->file->rename_partitions(path))) { if (error != 1) @@ -4785,7 +4785,7 @@ static bool mysql_drop_partitions(ALTER_PARTITION_PARAM_TYPE *lpt) int error; DBUG_ENTER("mysql_drop_partitions"); - build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, ""); + build_table_filename(path, sizeof(path), lpt->db, lpt->table_name, "", 0); if ((error= lpt->table->file->drop_partitions(path))) { lpt->table->file->print_error(error, MYF(0)); @@ -5136,7 +5136,7 @@ static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt) DBUG_ENTER("write_log_drop_shadow_frm"); build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, - lpt->table_name, "#"); + lpt->table_name, "#", 0); pthread_mutex_lock(&LOCK_gdl); if (write_log_replace_delete_frm(lpt, 0UL, NULL, (const char*)shadow_path, FALSE)) @@ -5184,9 +5184,9 @@ static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt) part_info->first_log_entry= NULL; build_table_filename(path, sizeof(path), lpt->db, - lpt->table_name, ""); + lpt->table_name, "", 0); build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, - lpt->table_name, "#"); + lpt->table_name, "#", 0); pthread_mutex_lock(&LOCK_gdl); if (write_log_replace_delete_frm(lpt, 0UL, shadow_path, path, TRUE)) goto error; @@ -5238,9 +5238,9 @@ static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt) part_info->first_log_entry= NULL; build_table_filename(path, sizeof(path), lpt->db, - lpt->table_name, ""); + lpt->table_name, "", 0); build_table_filename(tmp_path, sizeof(tmp_path), lpt->db, - lpt->table_name, "#"); + lpt->table_name, "#", 0); pthread_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, FALSE)) @@ -5295,9 +5295,9 @@ static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) DBUG_ENTER("write_log_add_change_partition"); build_table_filename(path, sizeof(path), lpt->db, - lpt->table_name, ""); + lpt->table_name, "", 0); build_table_filename(tmp_path, sizeof(tmp_path), lpt->db, - lpt->table_name, "#"); + lpt->table_name, "#", 0); pthread_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, FALSE)) @@ -5352,9 +5352,9 @@ static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) part_info->first_log_entry= NULL; build_table_filename(path, sizeof(path), lpt->db, - lpt->table_name, ""); + lpt->table_name, "", 0); build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, - lpt->table_name, "#"); + lpt->table_name, "#", 0); pthread_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, lpt->alter_info->flags & ALTER_REORGANIZE_PARTITION)) diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index e3468b2b5cf..73473ddd24b 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -157,14 +157,14 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) new_alias= new_table->table_name; } build_table_filename(name, sizeof(name), - new_table->db, new_alias, reg_ext); + new_table->db, new_alias, reg_ext, 0); if (!access(name,F_OK)) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); DBUG_RETURN(ren_table); // This can't be skipped } build_table_filename(name, sizeof(name), - ren_table->db, old_alias, reg_ext); + ren_table->db, old_alias, reg_ext, 0); frm_type= mysql_frm_type(thd, name, &table_type); switch (frm_type) @@ -178,7 +178,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) if (!(rc= mysql_rename_table(ha_resolve_by_legacy_type(thd, table_type), ren_table->db, old_alias, - new_table->db, new_alias))) + new_table->db, new_alias, 0))) { if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db, old_alias, @@ -194,7 +194,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) (void) mysql_rename_table(ha_resolve_by_legacy_type(thd, table_type), new_table->db, new_alias, - ren_table->db, old_alias); + ren_table->db, old_alias, 0); } } } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8f8c84c2db5..4b8e7f8f538 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -463,7 +463,6 @@ mysql_find_files(THD *thd,List *files, const char *db,const char *path, uint col_access=thd->col_access; #endif TABLE_LIST table_list; - char tbbuff[FN_REFLEN]; DBUG_ENTER("mysql_find_files"); if (wild && !wild[0]) @@ -480,8 +479,6 @@ mysql_find_files(THD *thd,List *files, const char *db,const char *path, DBUG_RETURN(-1); } - VOID(tablename_to_filename(tmp_file_prefix, tbbuff, sizeof(tbbuff))); - for (i=0 ; i < (uint) dirp->number_off_files ; i++) { char uname[NAME_LEN*3+1]; /* Unencoded name */ @@ -519,7 +516,7 @@ mysql_find_files(THD *thd,List *files, const char *db,const char *path, { // Return only .frm files which aren't temp files. if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),reg_ext) || - is_prefix(file->name,tbbuff)) + is_prefix(file->name, tmp_file_prefix)) continue; *ext=0; VOID(filename_to_tablename(file->name, uname, sizeof(uname))); @@ -688,7 +685,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname, } else { - length= build_table_filename(path, sizeof(path), dbname, "", ""); + length= build_table_filename(path, sizeof(path), dbname, "", "", 0); found_libchar= 0; if (length && path[length-1] == FN_LIBCHAR) { @@ -2530,7 +2527,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) } else { - len= build_table_filename(path, sizeof(path), base_name, "", ""); + len= build_table_filename(path, sizeof(path), base_name, "", "", 0); end= path + len; len= FN_LEN - len; if (mysql_find_files(thd, &files, base_name, @@ -2684,7 +2681,7 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond) (grant_option && !check_grant_db(thd, file_name))) #endif { - length= build_table_filename(path, sizeof(path), file_name, "", ""); + length= build_table_filename(path, sizeof(path), file_name, "", "", 0); found_libchar= 0; if (length && path[length-1] == FN_LIBCHAR) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index d9a43e4580f..a5aa490fdac 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -53,31 +53,77 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, #define MYSQL50_TABLE_NAME_PREFIX "#mysql50#" #define MYSQL50_TABLE_NAME_PREFIX_LENGTH 9 + +/* + Translate a file name to a table name (WL #1324). + + SYNOPSIS + filename_to_tablename() + from The file name in my_charset_filename. + to OUT The table name in system_charset_info. + to_length The size of the table name buffer. + + RETURN + Table name length. +*/ + uint filename_to_tablename(const char *from, char *to, uint to_length) { - uint errors, res= strconvert(&my_charset_filename, from, - system_charset_info, to, to_length, &errors); - if (errors) // Old 5.0 name + uint errors; + uint res; + DBUG_ENTER("filename_to_tablename"); + DBUG_PRINT("enter", ("from '%s'", from)); + + if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length)) { - res= strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) - to; - sql_print_error("Invalid (old?) table or database name '%s'", from); - /* - TODO: add a stored procedure for fix table and database names, - and mention its name in error log. - */ + /* Temporary table name. */ + res= (strnmov(to, from, to_length) - to); } - return res; + else + { + res= strconvert(&my_charset_filename, from, + system_charset_info, to, to_length, &errors); + if (errors) // Old 5.0 name + { + res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) - + to); + sql_print_error("Invalid (old?) table or database name '%s'", from); + /* + TODO: add a stored procedure for fix table and database names, + and mention its name in error log. + */ + } + } + + DBUG_PRINT("exit", ("to '%s'", to)); + DBUG_RETURN(res); } +/* + Translate a table name to a file name (WL #1324). + + SYNOPSIS + tablename_to_filename() + from The table name in system_charset_info. + to OUT The file name in my_charset_filename. + to_length The size of the file name buffer. + + RETURN + File name length. +*/ + uint tablename_to_filename(const char *from, char *to, uint to_length) { uint errors, length; + DBUG_ENTER("tablename_to_filename"); + DBUG_PRINT("enter", ("from '%s'", from)); + if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX, MYSQL50_TABLE_NAME_PREFIX_LENGTH)) - return (uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH, - to_length-1) - - (from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)); + DBUG_RETURN((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH, + to_length-1) - + (from + MYSQL50_TABLE_NAME_PREFIX_LENGTH))); length= strconvert(system_charset_info, from, &my_charset_filename, to, to_length, &errors); if (check_if_legal_tablename(to) && @@ -86,7 +132,8 @@ uint tablename_to_filename(const char *from, char *to, uint to_length) memcpy(to + length, "@@@", 4); length+= 3; } - return length; + DBUG_PRINT("exit", ("to '%s'", to)); + DBUG_RETURN(length); } @@ -95,52 +142,87 @@ uint tablename_to_filename(const char *from, char *to, uint to_length) SYNOPSIS build_table_filename() - buff where to write result - bufflen buff size - db database name, in system_charset_info - table table name, in system_charset_info - ext file extension + buff Where to write result in my_charset_filename. + bufflen buff size + db Database name in system_charset_info. + table_name Table name in system_charset_info. + ext File extension. + flags FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP + table_name is temporary, do not change. NOTES Uses database and table name, and extension to create a file name in mysql_data_dir. Database and table names are converted from system_charset_info into "fscs". + Unless flags indicate a temporary table name. + 'db' is always converted. 'ext' is not converted. - RETURN + The conversion suppression is required for ALTER TABLE. This + statement creates intermediate tables. These are regular + (non-temporary) tables with a temporary name. Their path names must + be derivable from the table name. So we cannot use + build_tmptable_filename() for them. + RETURN + path length */ - uint build_table_filename(char *buff, size_t bufflen, const char *db, - const char *table, const char *ext) + const char *table_name, const char *ext, uint flags) { uint length; char dbbuff[FN_REFLEN]; char tbbuff[FN_REFLEN]; - VOID(tablename_to_filename(table, tbbuff, sizeof(tbbuff))); + DBUG_ENTER("build_table_filename"); + + if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP + strnmov(tbbuff, table_name, sizeof(tbbuff)); + else + VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff))); + VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff))); - strxnmov(buff, bufflen, - mysql_data_home, "/", dbbuff, "/", tbbuff, ext, NullS); - length= unpack_filename(buff, buff); - return length; + length= strxnmov(buff, bufflen, mysql_data_home, "/", dbbuff, + "/", tbbuff, ext, NullS) - buff; + DBUG_PRINT("exit", ("buff: '%s'", buff)); + DBUG_RETURN(length); } +/* + Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext + + SYNOPSIS + build_tmptable_filename() + thd The thread handle. + buff Where to write result in my_charset_filename. + bufflen buff size + + NOTES + + Uses current_pid, thread_id, and tmp_table counter to create + a file name in mysql_tmpdir. + + RETURN + path length +*/ + uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen) { uint length; - char tbbuff[FN_REFLEN]; char tmp_table_name[tmp_file_prefix_length+22+22+22+3]; + DBUG_ENTER("build_tmptable_filename"); + my_snprintf(tmp_table_name, sizeof(tmp_table_name), "%s%lx_%lx_%x", tmp_file_prefix, current_pid, thd->thread_id, thd->tmp_table++); - VOID(tablename_to_filename(tmp_table_name, tbbuff, sizeof(tbbuff))); - strxnmov(buff, bufflen, mysql_tmpdir, "/", tbbuff, reg_ext, NullS); + + strxnmov(buff, bufflen, mysql_tmpdir, "/", tmp_table_name, reg_ext, NullS); length= unpack_filename(buff, buff); - return length; + DBUG_PRINT("exit", ("buff: '%s'", buff)); + DBUG_RETURN(length); } /* @@ -1203,7 +1285,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) Build shadow frm file name */ build_table_filename(shadow_path, sizeof(shadow_path), lpt->db, - lpt->table_name, "#"); + lpt->table_name, "#", 0); strxmov(shadow_frm_name, shadow_path, reg_ext, NullS); if (flags & WFRM_WRITE_SHADOW) { @@ -1287,7 +1369,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) Build frm file name */ build_table_filename(path, sizeof(path), lpt->db, - lpt->table_name, ""); + lpt->table_name, "", 0); strxmov(frm_name, path, reg_ext, NullS); /* When we are changing to use new frm file we need to ensure that we @@ -1608,7 +1690,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, alias= (lower_case_table_names == 2) ? table->alias : table->table_name; /* remove .frm file and engine files */ path_length= build_table_filename(path, sizeof(path), - db, alias, reg_ext); + db, alias, reg_ext, 0); } if (drop_temporary || (table_type == NULL && @@ -1732,15 +1814,30 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, } +/* + Quickly remove a table. + + SYNOPSIS + quick_rm_table() + base The handlerton handle. + db The database name. + table_name The table name. + flags flags for build_table_filename(). + + RETURN + 0 OK + != 0 Error +*/ + bool quick_rm_table(handlerton *base,const char *db, - const char *table_name) + const char *table_name, uint flags) { char path[FN_REFLEN]; bool error= 0; DBUG_ENTER("quick_rm_table"); uint path_length= build_table_filename(path, sizeof(path), - db, table_name, reg_ext); + db, table_name, reg_ext, flags); if (my_delete(path,MYF(0))) error= 1; /* purecov: inspected */ path[path_length - reg_ext_length]= '\0'; // Remove reg_ext @@ -2891,7 +2988,7 @@ static void set_table_default_charset(THD *thd, HA_CREATE_INFO db_info; char path[FN_REFLEN]; /* Abuse build_table_filename() to build the path to the db.opt file */ - build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE); + build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE, 0); load_db_opt(thd, path, &db_info); create_info->default_table_charset= db_info.default_table_charset; } @@ -3074,6 +3171,8 @@ bool mysql_create_table_internal(THD *thd, handler *file; bool error= TRUE; DBUG_ENTER("mysql_create_table_internal"); + DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d", + db, table_name, internal_tmp_table)); if (use_copy_create_info) { @@ -3293,7 +3392,8 @@ bool mysql_create_table_internal(THD *thd, start++; } #endif - path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext); + path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext, + internal_tmp_table ? FN_IS_TMP : 0); } /* Check if table already exists */ @@ -3337,9 +3437,13 @@ bool mysql_create_table_internal(THD *thd, */ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { + char dbbuff[FN_REFLEN]; + char tbbuff[FN_REFLEN]; bool create_if_not_exists = create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS; - if (ha_table_exists_in_engine(thd, db, table_name)) + VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff))); + VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff))); + if (ha_table_exists_in_engine(thd, dbbuff, tbbuff)) { DBUG_PRINT("info", ("Table with same name already existed in handler")); @@ -3491,12 +3595,30 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end) ** Alter a table definition ****************************************************************************/ + +/* + Rename a table. + + SYNOPSIS + mysql_rename_table() + base The handlerton handle. + old_db The old database name. + old_name The old table name. + new_db The new database name. + new_name The new table name. + flags flags for build_table_filename(). + FN_FROM_IS_TMP old_name is temporary. + FN_TO_IS_TMP new_name is temporary. + + RETURN + 0 OK + != 0 Error +*/ + bool -mysql_rename_table(handlerton *base, - const char *old_db, - const char *old_name, - const char *new_db, - const char *new_name) +mysql_rename_table(handlerton *base, const char *old_db, + const char *old_name, const char *new_db, + const char *new_name, uint flags) { THD *thd= current_thd; char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN]; @@ -3505,12 +3627,16 @@ mysql_rename_table(handlerton *base, handler *file; int error=0; DBUG_ENTER("mysql_rename_table"); + DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'", + old_db, old_name, new_db, new_name)); file= (base == NULL ? 0 : get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base)); - build_table_filename(from, sizeof(from), old_db, old_name, ""); - build_table_filename(to, sizeof(to), new_db, new_name, ""); + build_table_filename(from, sizeof(from), old_db, old_name, "", + flags & FN_FROM_IS_TMP); + build_table_filename(to, sizeof(to), new_db, new_name, "", + flags & FN_TO_IS_TMP); /* If lower_case_table_names == 2 (case-preserving but case-insensitive @@ -3522,12 +3648,14 @@ mysql_rename_table(handlerton *base, { strmov(tmp_name, old_name); my_casedn_str(files_charset_info, tmp_name); - build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, ""); + build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "", + flags & FN_FROM_IS_TMP); from_base= lc_from; strmov(tmp_name, new_name); my_casedn_str(files_charset_info, tmp_name); - build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, ""); + build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "", + flags & FN_TO_IS_TMP); to_base= lc_to; } @@ -3663,7 +3791,8 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, if (fn_format_relative_to_data_home(src_path, uname, backup_dir, reg_ext)) DBUG_RETURN(-1); // protect buffer overflow - build_table_filename(dst_path, sizeof(dst_path), db, table_name, reg_ext); + build_table_filename(dst_path, sizeof(dst_path), + db, table_name, reg_ext, 0); if (lock_and_wait_for_table_name(thd,table)) DBUG_RETURN(-1); @@ -3740,6 +3869,15 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, table= &tmp_table; pthread_mutex_unlock(&LOCK_open); } + /* + REPAIR TABLE ... USE_FRM for temporary tables makes little sense. + */ + if (table->s->tmp_table) + { + error= send_check_errmsg(thd, table_list, "repair", + "Cannot repair temporary table from .frm file"); + goto end; + } /* User gave us USE_FRM which means that the header in the index file is @@ -4437,7 +4575,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, else { build_table_filename(src_path, sizeof(src_path), - src_db, src_table, reg_ext); + src_db, src_table, reg_ext, 0); /* Resolve symlinks (for windows) */ unpack_filename(src_path, src_path); if (lower_case_table_names) @@ -4476,7 +4614,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, else { dst_path_length= build_table_filename(dst_path, sizeof(dst_path), - db, table_name, reg_ext); + db, table_name, reg_ext, 0); if (!access(dst_path, F_OK)) goto table_exists; } @@ -4526,7 +4664,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, else if (err) { (void) quick_rm_table(create_info->db_type, db, - table_name); /* purecov: inspected */ + table_name, 0); /* purecov: inspected */ goto err; /* purecov: inspected */ } @@ -5005,8 +5143,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, db=table_list->db; if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db)) new_db= db; - build_table_filename(reg_path, sizeof(reg_path), db, table_name, reg_ext); - build_table_filename(path, sizeof(path), db, table_name, ""); + build_table_filename(reg_path, sizeof(reg_path), db, table_name, reg_ext, 0); + build_table_filename(path, sizeof(path), db, table_name, "", 0); used_fields=create_info->used_fields; @@ -5023,6 +5161,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, /* Check that we are not trying to rename to an existing table */ if (new_name) { + DBUG_PRINT("info", ("new_db.new_name: '%s'.'%s'", new_db, new_name)); strmov(new_name_buff,new_name); strmov(new_alias= new_alias_buff, new_name); if (lower_case_table_names) @@ -5055,11 +5194,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } else { - char dir_buff[FN_REFLEN]; - strxnmov(dir_buff, sizeof(dir_buff)-1, - mysql_real_data_home, new_db, NullS); - if (!access(fn_format(new_name_buff,new_name_buff,dir_buff,reg_ext,0), - F_OK)) + build_table_filename(new_name_buff, sizeof(new_name_buff), + new_db, new_name_buff, reg_ext, 0); + if (!access(new_name_buff, F_OK)) { /* Table will be closed in do_command() */ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); @@ -5142,13 +5279,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, *fn_ext(new_name)=0; table->s->version= 0; // Force removal of table def close_cached_table(thd, table); - if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias)) + if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0)) error= -1; else if (Table_triggers_list::change_table_name(thd, db, table_name, new_db, new_alias)) { VOID(mysql_rename_table(old_db_type, new_db, new_alias, db, - table_name)); + table_name, 0)); error= -1; } } @@ -5776,7 +5913,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, { char path[FN_REFLEN]; /* table is a normal table: Create temporary table in same directory */ - build_table_filename(path, sizeof(path), new_db, tmp_name, ""); + build_table_filename(path, sizeof(path), new_db, tmp_name, "", + FN_IS_TMP); new_table=open_temporary_table(thd, path, new_db, tmp_name,0); } if (!new_table) @@ -5992,7 +6130,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, VOID(pthread_mutex_lock(&LOCK_open)); if (error) { - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); + VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } @@ -6014,7 +6152,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, { error=1; my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff); - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); + VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } @@ -6042,22 +6180,24 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, error=0; if (!need_copy_table) new_db_type=old_db_type= NULL; // this type cannot happen in regular ALTER - if (mysql_rename_table(old_db_type,db,table_name,db,old_name)) + if (mysql_rename_table(old_db_type, db, table_name, db, old_name, + FN_TO_IS_TMP)) { error=1; - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); + VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); } else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db, - new_alias) || + new_alias, FN_FROM_IS_TMP) || (new_name != table_name || new_db != db) && // we also do rename Table_triggers_list::change_table_name(thd, db, table_name, new_db, new_alias)) - - { // Try to get everything back + { + /* Try to get everything back. */ error=1; - VOID(quick_rm_table(new_db_type,new_db,new_alias)); - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); - VOID(mysql_rename_table(old_db_type,db,old_name,db,alias)); + VOID(quick_rm_table(new_db_type,new_db,new_alias, 0)); + VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); + VOID(mysql_rename_table(old_db_type, db, old_name, db, alias, + FN_FROM_IS_TMP)); } if (error) { @@ -6101,7 +6241,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, table->s->version= 0; // Force removal of table def close_cached_table(thd,table); } - VOID(quick_rm_table(old_db_type,db,old_name)); + VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP)); } else { @@ -6118,7 +6258,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, /* end threads waiting on lock */ mysql_lock_abort(thd,table, TRUE); } - VOID(quick_rm_table(old_db_type,db,old_name)); + VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP)); if (close_data_tables(thd,db,table_name) || reopen_tables(thd,1,0)) { // This shouldn't happen @@ -6168,7 +6308,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, shutdown. */ char path[FN_REFLEN]; - build_table_filename(path, sizeof(path), new_db, table_name, ""); + build_table_filename(path, sizeof(path), new_db, table_name, "", 0); table=open_temporary_table(thd, path, new_db, tmp_name,0); if (table) { @@ -6199,7 +6339,7 @@ end_temporary: close_temporary_table(thd, new_table, 1, 1); } else - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); + VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); err: DBUG_RETURN(TRUE); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 5abdfa27d58..52bcb88ad8e 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -457,12 +457,12 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, */ file.length= build_table_filename(file_buff, FN_REFLEN-1, tables->db, tables->table_name, - triggers_file_ext); + triggers_file_ext, 0); file.str= file_buff; trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1, tables->db, lex->spname->m_name.str, - trigname_file_ext); + trigname_file_ext, 0); trigname_file.str= trigname_buff; /* Use the filesystem to enforce trigger namespace constraints. */ @@ -568,7 +568,7 @@ err_with_cleanup: static bool rm_trigger_file(char *path, const char *db, const char *table_name) { - build_table_filename(path, FN_REFLEN-1, db, table_name, triggers_file_ext); + build_table_filename(path, FN_REFLEN-1, db, table_name, triggers_file_ext, 0); return my_delete(path, MYF(MY_WME)); } @@ -591,7 +591,8 @@ static bool rm_trigger_file(char *path, const char *db, static bool rm_trigname_file(char *path, const char *db, const char *trigger_name) { - build_table_filename(path, FN_REFLEN-1, db, trigger_name, trigname_file_ext); + build_table_filename(path, FN_REFLEN-1, + db, trigger_name, trigname_file_ext, 0); return my_delete(path, MYF(MY_WME)); } @@ -617,7 +618,7 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db, LEX_STRING file; file.length= build_table_filename(file_buff, FN_REFLEN-1, db, table_name, - triggers_file_ext); + triggers_file_ext, 0); file.str= file_buff; return sql_create_definition_file(NULL, &file, &triggers_file_type, (gptr)triggers, triggers_file_parameters, @@ -792,7 +793,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, DBUG_ENTER("Table_triggers_list::check_n_load"); path.length= build_table_filename(path_buff, FN_REFLEN-1, - db, table_name, triggers_file_ext); + db, table_name, triggers_file_ext, 0); path.str= path_buff; // QQ: should we analyze errno somehow ? @@ -1141,7 +1142,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) path.length= build_table_filename(path_buff, FN_REFLEN-1, trig->m_db.str, trig->m_name.str, - trigname_file_ext); + trigname_file_ext, 0); path.str= path_buff; if (access(path_buff, F_OK)) @@ -1348,7 +1349,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name, { trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1, db_name, trigger->str, - trigname_file_ext); + trigname_file_ext, 0); trigname_file.str= trigname_buff; trigname.trigger_table= *new_table_name; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 94ece79da81..f77953bc99e 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -606,11 +606,11 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, /* print file name */ dir.length= build_table_filename(dir_buff, sizeof(dir_buff), - view->db, "", ""); + view->db, "", "", 0); dir.str= dir_buff; path.length= build_table_filename(path_buff, sizeof(path_buff), - view->db, view->table_name, reg_ext); + view->db, view->table_name, reg_ext, 0); path.str= path_buff; file.str= path.str + dir.length; @@ -1237,7 +1237,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) TABLE_SHARE *share; bool type= 0; build_table_filename(path, sizeof(path), - view->db, view->table_name, reg_ext); + view->db, view->table_name, reg_ext, 0); VOID(pthread_mutex_lock(&LOCK_open)); if (access(path, F_OK) || (type= (mysql_frm_type(thd, path, ¬_used) != FRMTYPE_VIEW))) diff --git a/sql/table.cc b/sql/table.cc index 8bee8bf1598..ec790f7ba7d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -68,7 +68,7 @@ static byte *get_field_name(Field **buff, uint *length, char *fn_rext(char *name) { char *res= strrchr(name, '.'); - if (res && !strcmp(res, ".frm")) + if (res && !strcmp(res, reg_ext)) return res; return name + strlen(name); } @@ -95,10 +95,13 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, TABLE_SHARE *share; char path[FN_REFLEN]; uint path_length; + DBUG_ENTER("alloc_table_share"); + DBUG_PRINT("enter", ("table: '%s'.'%s'", + table_list->db, table_list->table_name)); path_length= build_table_filename(path, sizeof(path) - 1, table_list->db, - table_list->table_name, ""); + table_list->table_name, "", 0); init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); if ((share= (TABLE_SHARE*) alloc_root(&mem_root, sizeof(*share) + key_length + @@ -148,7 +151,7 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); pthread_cond_init(&share->cond, NULL); } - return share; + DBUG_RETURN(share); } @@ -179,6 +182,7 @@ void init_tmp_table_share(TABLE_SHARE *share, const char *key, const char *path) { DBUG_ENTER("init_tmp_table_share"); + DBUG_PRINT("enter", ("table: '%s'.'%s'", key, table_name)); bzero((char*) share, sizeof(*share)); init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); @@ -286,7 +290,8 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) char path[FN_REFLEN]; MEM_ROOT **root_ptr, *old_root; DBUG_ENTER("open_table_def"); - DBUG_PRINT("enter", ("name: '%s.%s'",share->db.str, share->table_name.str)); + DBUG_PRINT("enter", ("table: '%s'.'%s' path: '%s'", share->db.str, + share->table_name.str, share->normalized_path.str)); error= 1; error_given= 0; diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 58d86790c0a..18d12d66c29 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -3414,8 +3414,8 @@ row_is_mysql_tmp_table_name( const char* name) /* in: table name in the form 'database/tablename' */ { - /* return(strstr(name, "/#sql") != NULL); */ - return(strstr(name, "/@0023sql") != NULL); + return(strstr(name, "/#sql") != NULL); + /* return(strstr(name, "/@0023sql") != NULL); */ } /******************************************************************** From c8ad865ffe1afbf2149b5a0b27775c5ea70f9516 Mon Sep 17 00:00:00 2001 From: "ingo/istruewing@chilla.local" <> Date: Wed, 2 Aug 2006 18:39:21 +0200 Subject: [PATCH 8/9] Bug#18775 - Temporary table from alter table visible to other threads Reverting part of the patch. NDB has unencoded names in their data dictionary. --- sql/sql_table.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2a6f30a81dc..9d28e0496b1 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3435,13 +3435,9 @@ bool mysql_create_table_internal(THD *thd, */ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { - char dbbuff[FN_REFLEN]; - char tbbuff[FN_REFLEN]; bool create_if_not_exists = create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS; - VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff))); - VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff))); - if (ha_table_exists_in_engine(thd, dbbuff, tbbuff)) + if (ha_table_exists_in_engine(thd, db, table_name)) { DBUG_PRINT("info", ("Table with same name already existed in handler")); From ff329207192022626518cae27c27f33c70701880 Mon Sep 17 00:00:00 2001 From: "ingo/istruewing@chilla.local" <> Date: Thu, 3 Aug 2006 08:12:56 +0200 Subject: [PATCH 9/9] Bug#18775 - Temporary table from alter table visible to other threads New test cases. Names with umlauts don't compare well on Windows. --- mysql-test/r/alter_table.result | 55 ++++++++++++++++++--------------- mysql-test/r/backup.result | 20 ++++++------ mysql-test/t/alter_table.test | 39 +++++++++-------------- mysql-test/t/backup.test | 16 +++++----- 4 files changed, 63 insertions(+), 67 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 3095d5337ed..d3657d84678 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -657,43 +657,45 @@ SELECT * FROM t1; v b abc 5 DROP TABLE t1; -DROP DATABASE IF EXISTS mysqltest; -CREATE DATABASE mysqltest; -use mysqltest; -DROP TABLE IF EXISTS `t1_nägel`, `t1_blüten`; -CREATE TABLE `t1_nägel` (c1 INT); -ALTER TABLE `t1_nägel` RENAME `t1_blüten`; -CREATE TABLE `t1_nägel` (c1 INT); -ALTER TABLE `t1_nägel` RENAME `t1_blüten`; -ERROR 42S01: Table 't1_blЭten' already exists -DROP TABLE `t1_nägel`, `t1_blüten`; -CREATE TEMPORARY TABLE `tt1_nägel` (c1 INT); -ALTER TABLE `tt1_nägel` RENAME `tt1_blüten`; -CREATE TEMPORARY TABLE `tt1_nägel` (c1 INT); -ALTER TABLE `tt1_nägel` RENAME `tt1_blüten`; -ERROR 42S01: Table 'tt1_blЭten' already exists -SHOW CREATE TABLE `tt1_blüten`; +DROP TABLE IF EXISTS `t+1`, `t+2`; +CREATE TABLE `t+1` (c1 INT); +ALTER TABLE `t+1` RENAME `t+2`; +CREATE TABLE `t+1` (c1 INT); +ALTER TABLE `t+1` RENAME `t+2`; +ERROR 42S01: Table 't+2' already exists +DROP TABLE `t+1`, `t+2`; +CREATE TEMPORARY TABLE `tt+1` (c1 INT); +ALTER TABLE `tt+1` RENAME `tt+2`; +CREATE TEMPORARY TABLE `tt+1` (c1 INT); +ALTER TABLE `tt+1` RENAME `tt+2`; +ERROR 42S01: Table 'tt+2' already exists +SHOW CREATE TABLE `tt+1`; Table Create Table -tt1_blüten CREATE TEMPORARY TABLE `tt1_blüten` ( +tt+1 CREATE TEMPORARY TABLE `tt+1` ( `c1` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -DROP TABLE `tt1_nägel`, `tt1_blüten`; +SHOW CREATE TABLE `tt+2`; +Table Create Table +tt+2 CREATE TEMPORARY TABLE `tt+2` ( + `c1` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE `tt+1`, `tt+2`; CREATE TABLE `#sql1` (c1 INT); CREATE TABLE `@0023sql2` (c1 INT); SHOW TABLES; -Tables_in_mysqltest +Tables_in_test #sql1 @0023sql2 RENAME TABLE `#sql1` TO `@0023sql1`; RENAME TABLE `@0023sql2` TO `#sql2`; SHOW TABLES; -Tables_in_mysqltest +Tables_in_test #sql2 @0023sql1 ALTER TABLE `@0023sql1` RENAME `#sql-1`; ALTER TABLE `#sql2` RENAME `@0023sql-2`; SHOW TABLES; -Tables_in_mysqltest +Tables_in_test #sql-1 @0023sql-2 INSERT INTO `#sql-1` VALUES (1); @@ -702,18 +704,21 @@ DROP TABLE `#sql-1`, `@0023sql-2`; CREATE TEMPORARY TABLE `#sql1` (c1 INT); CREATE TEMPORARY TABLE `@0023sql2` (c1 INT); SHOW TABLES; -Tables_in_mysqltest +Tables_in_test ALTER TABLE `#sql1` RENAME `@0023sql1`; ALTER TABLE `@0023sql2` RENAME `#sql2`; SHOW TABLES; -Tables_in_mysqltest +Tables_in_test INSERT INTO `#sql2` VALUES (1); INSERT INTO `@0023sql1` VALUES (2); +SHOW CREATE TABLE `#sql2`; +Table Create Table +#sql2 CREATE TEMPORARY TABLE `#sql2` ( + `c1` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 SHOW CREATE TABLE `@0023sql1`; Table Create Table @0023sql1 CREATE TEMPORARY TABLE `@0023sql1` ( `c1` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE `#sql2`, `@0023sql1`; -use test; -DROP DATABASE mysqltest; diff --git a/mysql-test/r/backup.result b/mysql-test/r/backup.result index 05761240ca7..a4d1b18fe61 100644 --- a/mysql-test/r/backup.result +++ b/mysql-test/r/backup.result @@ -101,23 +101,23 @@ test.t5 backup status OK Warnings: Warning 1541 The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead. drop table t5; -DROP TABLE IF EXISTS `t-blüten`; -CREATE TABLE `t-blüten` (c1 INT); -INSERT INTO `t-blüten` VALUES (1), (2), (3); -BACKUP TABLE `t-blüten` TO '../tmp'; +DROP TABLE IF EXISTS `t+1`; +CREATE TABLE `t+1` (c1 INT); +INSERT INTO `t+1` VALUES (1), (2), (3); +BACKUP TABLE `t+1` TO '../tmp'; Table Op Msg_type Msg_text -test.t-blüten backup status OK +test.t+1 backup status OK Warnings: Warning 1541 The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead. -DROP TABLE `t-blüten`; -RESTORE TABLE `t-blüten` FROM '../tmp'; +DROP TABLE `t+1`; +RESTORE TABLE `t+1` FROM '../tmp'; Table Op Msg_type Msg_text -test.t-blüten restore status OK +test.t+1 restore status OK Warnings: Warning 1541 The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead. -SELECT * FROM `t-blüten`; +SELECT * FROM `t+1`; c1 1 2 3 -DROP TABLE `t-blüten`; +DROP TABLE `t+1`; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index f6af92e0044..168d011a2ac 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -488,32 +488,26 @@ DROP TABLE t1; # # Bug#18775 - Temporary table from alter table visible to other threads # -# Use a special database to avoid name clashes with user tables. +# Check if special characters work and duplicates are detected. --disable_warnings -DROP DATABASE IF EXISTS mysqltest; +DROP TABLE IF EXISTS `t+1`, `t+2`; --enable_warnings -CREATE DATABASE mysqltest; -use mysqltest; -# -# Check if non-ASCII alphabetic characters work and duplicates are detected. ---disable_warnings -DROP TABLE IF EXISTS `t1_nägel`, `t1_blüten`; ---enable_warnings -CREATE TABLE `t1_nägel` (c1 INT); -ALTER TABLE `t1_nägel` RENAME `t1_blüten`; -CREATE TABLE `t1_nägel` (c1 INT); +CREATE TABLE `t+1` (c1 INT); +ALTER TABLE `t+1` RENAME `t+2`; +CREATE TABLE `t+1` (c1 INT); --error ER_TABLE_EXISTS_ERROR -ALTER TABLE `t1_nägel` RENAME `t1_blüten`; -DROP TABLE `t1_nägel`, `t1_blüten`; +ALTER TABLE `t+1` RENAME `t+2`; +DROP TABLE `t+1`, `t+2`; # # Same for temporary tables though these names do not become file names. -CREATE TEMPORARY TABLE `tt1_nägel` (c1 INT); -ALTER TABLE `tt1_nägel` RENAME `tt1_blüten`; -CREATE TEMPORARY TABLE `tt1_nägel` (c1 INT); +CREATE TEMPORARY TABLE `tt+1` (c1 INT); +ALTER TABLE `tt+1` RENAME `tt+2`; +CREATE TEMPORARY TABLE `tt+1` (c1 INT); --error ER_TABLE_EXISTS_ERROR -ALTER TABLE `tt1_nägel` RENAME `tt1_blüten`; -SHOW CREATE TABLE `tt1_blüten`; -DROP TABLE `tt1_nägel`, `tt1_blüten`; +ALTER TABLE `tt+1` RENAME `tt+2`; +SHOW CREATE TABLE `tt+1`; +SHOW CREATE TABLE `tt+2`; +DROP TABLE `tt+1`, `tt+2`; # # Check if special characters as in tmp_file_prefix work. CREATE TABLE `#sql1` (c1 INT); @@ -538,10 +532,7 @@ ALTER TABLE `@0023sql2` RENAME `#sql2`; SHOW TABLES; INSERT INTO `#sql2` VALUES (1); INSERT INTO `@0023sql1` VALUES (2); +SHOW CREATE TABLE `#sql2`; SHOW CREATE TABLE `@0023sql1`; DROP TABLE `#sql2`, `@0023sql1`; -# -# Cleanup -use test; -DROP DATABASE mysqltest; diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test index fa6bbc21813..61bde0cecb0 100644 --- a/mysql-test/t/backup.test +++ b/mysql-test/t/backup.test @@ -65,15 +65,15 @@ drop table t5; # # Backup did not encode table names. --disable_warnings -DROP TABLE IF EXISTS `t-blüten`; +DROP TABLE IF EXISTS `t+1`; --enable_warnings -CREATE TABLE `t-blüten` (c1 INT); -INSERT INTO `t-blüten` VALUES (1), (2), (3); -BACKUP TABLE `t-blüten` TO '../tmp'; -DROP TABLE `t-blüten`; +CREATE TABLE `t+1` (c1 INT); +INSERT INTO `t+1` VALUES (1), (2), (3); +BACKUP TABLE `t+1` TO '../tmp'; +DROP TABLE `t+1`; # # Same for restore. -RESTORE TABLE `t-blüten` FROM '../tmp'; -SELECT * FROM `t-blüten`; -DROP TABLE `t-blüten`; +RESTORE TABLE `t+1` FROM '../tmp'; +SELECT * FROM `t+1`; +DROP TABLE `t+1`;