# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: mattias.jonsson@sun.com-20081009134110-ora2sglw24039ppa # target_branch: file:///Users/mattiasj/clones/bzrroot/60-bugteam/ # testament_sha1: a3d049f168d8733cdafe3b3a0de20cce71d5d0f1 # timestamp: 2008-11-05 21:25:47 +0100 # base_revision_id: chad@mysql.com-20080808144421-hlpsy443bzwmx3r4 # # Begin patch === modified file 'mysql-test/r/partition_innodb.result' --- mysql-test/r/partition_innodb.result 2008-06-12 00:08:07 +0000 +++ mysql-test/r/partition_innodb.result 2008-10-09 13:41:10 +0000 @@ -1,3 +1,36 @@ +SET NAMES utf8; +CREATE TABLE t1 (a INT, PRIMARY KEY (a)) +ENGINE=InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION p0 VALUES LESS THAN (100) +(SUBPARTITION sp0, +SUBPARTITION sp1), +PARTITION p1 VALUES LESS THAN (MAXVALUE) +(SUBPARTITION sp2, +SUBPARTITION sp3)); +INSERT INTO t1 VALUES (0), (2), (6), (10), (14), (18), (22); +START TRANSACTION; +# con1 +SET NAMES utf8; +START TRANSACTION; +# default connection +UPDATE t1 SET a = 16 WHERE a = 0; +# con1 +UPDATE t1 SET a = 8 WHERE a = 22; +UPDATE t1 SET a = 12 WHERE a = 0; +# default connection +UPDATE t1 SET a = 4 WHERE a = 22; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +# First table reported in 'SHOW ENGINE InnoDB STATUS' +SHOW ENGINE InnoDB STATUS; +Type Name Status +InnoDB Database `test`, Table `t1`, Partition `p0`, Subpartition `sp0` +# con1 +ROLLBACK; +# default connection +DROP TABLE t1; +SET NAMES DEFAULT; # Bug#32948 CREATE TABLE t1 (c1 INT, PRIMARY KEY (c1)) ENGINE=INNODB; CREATE TABLE t2 (c1 INT, PRIMARY KEY (c1), === modified file 'mysql-test/t/partition_innodb.test' --- mysql-test/t/partition_innodb.test 2008-06-12 00:08:07 +0000 +++ mysql-test/t/partition_innodb.test 2008-10-09 13:41:10 +0000 @@ -1,6 +1,56 @@ --source include/have_partition.inc --source include/have_innodb.inc +# Bug#32430 - show engine innodb status causes errors +# +SET NAMES utf8; +CREATE TABLE t1 (a INT, PRIMARY KEY (a)) +ENGINE=InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION p0 VALUES LESS THAN (100) + (SUBPARTITION sp0, + SUBPARTITION sp1), + PARTITION p1 VALUES LESS THAN (MAXVALUE) + (SUBPARTITION sp2, + SUBPARTITION sp3)); +INSERT INTO t1 VALUES (0), (2), (6), (10), (14), (18), (22); +START TRANSACTION; +--echo # con1 +connect(con1,localhost,root,,); +SET NAMES utf8; +START TRANSACTION; +--echo # default connection +connection default; +UPDATE t1 SET a = 16 WHERE a = 0; +--echo # con1 +connection con1; +UPDATE t1 SET a = 8 WHERE a = 22; +let $id_1= `SELECT CONNECTION_ID()`; +SEND; +UPDATE t1 SET a = 12 WHERE a = 0; +--echo # default connection +connection default; +let $wait_timeout= 2; +let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE ID = $id_1 AND STATE = 'Searching rows for update'; +--source include/wait_condition.inc +#--echo # tested wait condition $wait_condition_reps times +--error ER_LOCK_DEADLOCK +UPDATE t1 SET a = 4 WHERE a = 22; +--echo # First table reported in 'SHOW ENGINE InnoDB STATUS' +--replace_regex /.* index .* in (.*) trx id .*/\1/ +SHOW ENGINE InnoDB STATUS; +--echo # con1 +connection con1; +REAP; +ROLLBACK; +disconnect con1; +--echo # default connection +connection default; +DROP TABLE t1; +SET NAMES DEFAULT; + # Bug#32948 - FKs allowed to reference partitioned table # -- echo # Bug#32948 === modified file 'sql/mysql_priv.h' --- sql/mysql_priv.h 2008-08-07 03:05:33 +0000 +++ sql/mysql_priv.h 2008-10-09 13:41:10 +0000 @@ -2322,6 +2322,9 @@ #if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS uint strconvert(CHARSET_INFO *from_cs, const char *from, CHARSET_INFO *to_cs, char *to, uint to_length, uint *errors); +/* depends on errmsg.txt Database `db`, Table `t` ... */ +#define EXPLAIN_FILENAME_MAX_EXTRA_LENGTH 63 +uint explain_filename(const char *from, char *to, uint to_length); uint filename_to_tablename(const char *from, char *to, uint to_length); uint tablename_to_filename(const char *from, char *to, uint to_length); #endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */ === modified file 'sql/share/errmsg.txt' --- sql/share/errmsg.txt 2008-08-06 14:39:03 +0000 +++ sql/share/errmsg.txt 2008-10-09 13:41:10 +0000 @@ -6372,3 +6372,23 @@ eng "Restore failed to obtain the name locks on the tables." ER_BACKUP_RELEASE_NAME_LOCK_FAILED eng "Restore failed to release the name locks on the tables." +# When updating these, please update EXPLAIN_FILENAME_MAX_EXTRA_LENGTH in +# mysql_priv.h with the new maximal additional length for explain_filename. +ER_DATABASE_NAME + eng "Database `%s`" + swe "Databas `%s`" +ER_TABLE_NAME + eng "Table `%s`" + swe "Tabell `%s`" +ER_PARTITION_NAME + eng "Partition `%s`" + swe "Partition `%s`" +ER_SUBPARTITION_NAME + eng "Subpartition `%s`" + swe "Subpartition `%s`" +ER_TEMPORARY_NAME + eng "Temporary" + swe "Temporär" +ER_RENAMED_NAME + eng "Renamed" + swe "Namnändrad" === modified file 'sql/sql_table.cc' --- sql/sql_table.cc 2008-07-26 16:38:20 +0000 +++ sql/sql_table.cc 2008-10-09 13:41:10 +0000 @@ -68,6 +68,195 @@ #endif +/** + @brief Helper function for explain_filename +*/ +static char* add_identifier(char *to_p, const char * end_p, + const char* name, uint name_len, int errcode) +{ + uint res; + uint errors; + const char *conv_name; + char tmp_name[FN_REFLEN]; + char conv_string[FN_REFLEN]; + + DBUG_ENTER("add_identifier"); + if (!name[name_len]) + conv_name= name; + else + { + strnmov(tmp_name, name, name_len); + tmp_name[name_len]= 0; + conv_name= tmp_name; + } + res= strconvert(&my_charset_filename, conv_name, system_charset_info, + conv_string, FN_REFLEN, &errors); + if (!res || errors) + conv_name= name; + else + { + DBUG_PRINT("info", ("conv '%s' -> '%s'", conv_name, conv_string)); + conv_name= conv_string; + } + + to_p+= my_snprintf(to_p, end_p - to_p, ER(errcode), conv_name); + return to_p; +} + + +/** + @brief Explain a file name by split it to [database,]tablename[,partname...] + + @details Break down the filename to its logic parts and add the partname + (database, table, partition, subpartition). + filename_to_tablename cannot be used on partitions, due to the #P# part. + There can be up to 6 '#', #P# for partition, #SP# for subpartition + and #TMP# or #REN# for temporary or renamed partitions. + + @param from The null terminated file name in my_charset_filename + @param to The explained name in system_charset_info + @param to_length size of to buffer + + @retval length of returned string +*/ + +uint explain_filename(const char *from, char *to, uint to_length) +{ + uint res= 0; + char *to_p= to; + char *end_p= to_p + to_length; + const char *db_name= NULL; + int db_name_len= 0; + const char *table_name; + int table_name_len= 0; + const char *part_name= NULL; + int part_name_len= 0; + const char *subpart_name= NULL; + int subpart_name_len= 0; + int temp_or_renamed= 0; /* 1= temp, 2= renamed */ + const char *tmp_p; + DBUG_ENTER("explain_filename"); + DBUG_PRINT("enter", ("from '%s'", from)); + /* + if '/' then take last directory part as database + Compose the explained name as + [Database %s, ]Table %s[,[ Temporary| Renamed] Partition %s + [, Subpartition %s]] + */ + tmp_p= from; + table_name= from; + /* '/' is the directory separator, not FN_LIB_CHAR */ + while ((tmp_p= strchr(tmp_p, '/'))) + { + db_name= table_name; + /* calculate the length */ + db_name_len= tmp_p - db_name; + tmp_p++; + table_name= tmp_p; + } + tmp_p= table_name; + while (!res && (tmp_p= strchr(tmp_p, '#'))) + { + tmp_p++; + switch (tmp_p[0]) { + case 'P': + case 'p': + if (tmp_p[1] == '#') + part_name= tmp_p + 2; + else + res= 1; + tmp_p+= 2; + break; + case 'S': + case 's': + if (tmp_p[2] == '#' && (tmp_p[1] == 'P' || tmp_p[1] == 'p')) + { + part_name_len= tmp_p - part_name - 1; + subpart_name= tmp_p + 3; + } + else + res= 2; + tmp_p+= 3; + break; + case 'T': + case 't': + if (tmp_p[3] == '#' && (tmp_p[1] == 'M' || tmp_p[1] == 'm') && + (tmp_p[1] == 'P' || tmp_p[1] == 'p') && !tmp_p[4]) + temp_or_renamed= 1; /* 1= temp, 2= renamed */ + else + res= 3; + tmp_p+= 4; + break; + case 'R': + case 'r': + if (tmp_p[3] == '#' && (tmp_p[1] == 'E' || tmp_p[1] == 'e') && + (tmp_p[1] == 'N' || tmp_p[1] == 'n') && !tmp_p[4]) + temp_or_renamed= 2; /* 1= temp, 2= renamed */ + else + res= 4; + tmp_p+= 4; + break; + default: + res= 5; + } + } + if (res) + { + /* Better to give something back if we fail parsing, than nothing at all */ + DBUG_PRINT("info", ("Error in explain_filename: %u", res)); + sql_print_warning("Invalid (old?) table or database name '%s'", from); + DBUG_RETURN(my_snprintf(to, to_length, + "", + res, from)); + } + if (part_name) + { + table_name_len= part_name - table_name - 3; + if (subpart_name) + subpart_name_len= strlen(subpart_name); + else + part_name_len= strlen(part_name); + if (temp_or_renamed) + { + if (subpart_name) + subpart_name_len-= 5; + else + part_name_len-= 5; + } + } + if (db_name) + { + to_p= add_identifier(to_p, end_p, db_name, db_name_len, + ER_DATABASE_NAME); + to_p= strnmov(to_p, ", ", end_p - to_p); + } + to_p= add_identifier(to_p, end_p, table_name, table_name_len, + ER_TABLE_NAME); + if (part_name) + { + to_p= strnmov(to_p, ", ", end_p - to_p); + if (temp_or_renamed) + { + if (temp_or_renamed == 1) + to_p= strnmov(to_p, ER(ER_TEMPORARY_NAME), end_p - to_p); + else + to_p= strnmov(to_p, ER(ER_RENAMED_NAME), end_p - to_p); + to_p= strnmov(to_p, " ", end_p - to_p); + } + to_p= add_identifier(to_p, end_p, part_name, part_name_len, + ER_PARTITION_NAME); + if (subpart_name) + { + to_p= strnmov(to_p, ", ", end_p - to_p); + to_p= add_identifier(to_p, end_p, subpart_name, subpart_name_len, + ER_SUBPARTITION_NAME); + } + } + DBUG_PRINT("exit", ("to '%s'", to)); + DBUG_RETURN(to_p - to); +} + + /* Translate a file name to a table name (WL #1324). === modified file 'storage/innobase/dict/dict0dict.c' --- storage/innobase/dict/dict0dict.c 2008-06-12 00:08:07 +0000 +++ storage/innobase/dict/dict0dict.c 2008-10-09 13:41:10 +0000 @@ -4210,6 +4210,6 @@ { fputs("index ", file); ut_print_name(file, trx, FALSE, index->name); - fputs(" of table ", file); + fputs(" in ", file); ut_print_name(file, trx, TRUE, index->table_name); } === modified file 'storage/innobase/handler/ha_innodb.cc' --- storage/innobase/handler/ha_innodb.cc 2008-06-12 00:08:07 +0000 +++ storage/innobase/handler/ha_innodb.cc 2008-10-09 13:41:10 +0000 @@ -1271,14 +1271,14 @@ int q; if (table_id) { - /* Decode the table name. The filename_to_tablename() + /* Decode the table name. The explain_filename() function expects a NUL-terminated string. The input and output strings buffers must not be shared. The function only produces more output when the name contains other characters than [0-9A-Z_a-z]. */ char* temp_name = (char*) my_malloc((uint) namelen + 1, MYF(MY_WME)); uint qnamelen = (uint) (namelen - + (1 + sizeof srv_mysql50_table_name_prefix)); + + (1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH)); if (temp_name) { qname = (char*) my_malloc(qnamelen, MYF(MY_WME)); @@ -1286,7 +1286,7 @@ memcpy(temp_name, name, namelen); temp_name[namelen] = 0; s = qname; - namelen = filename_to_tablename(temp_name, + namelen = explain_filename(temp_name, qname, qnamelen); } my_free(temp_name, MYF(0)); @@ -1301,7 +1301,7 @@ s, (int) namelen); } - if (q == EOF) { + if (q == EOF || table_id) { fwrite(s, 1, namelen, f); } else { const char* e = s + namelen; === modified file 'storage/innobase/ut/ut0ut.c' --- storage/innobase/ut/ut0ut.c 2008-06-12 00:08:07 +0000 +++ storage/innobase/ut/ut0ut.c 2008-10-09 13:41:10 +0000 @@ -487,22 +487,7 @@ #ifdef UNIV_HOTBACKUP fwrite(name, 1, namelen, f); #else - if (table_id) { - char* slash = memchr(name, '/', namelen); - if (!slash) { - - goto no_db_name; - } - - /* Print the database name and table name separately. */ - innobase_print_identifier(f, trx, TRUE, name, slash - name); - putc('.', f); - innobase_print_identifier(f, trx, TRUE, slash + 1, - namelen - (slash - name) - 1); - } else { -no_db_name: - innobase_print_identifier(f, trx, table_id, name, namelen); - } + innobase_print_identifier(f, trx, table_id, name, namelen); #endif } # Begin bundle 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