List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:July 7 2008 10:58am
Subject:bzr commit into mysql-6.0 branch (mattiasj:2691) Bug#32430
View as plain text  
#At file:///Users/mattiasj/clones/bzrroot/b32430-60-bugteam/

 2691 Mattias Jonsson	2008-07-07
      Bug#32430 'show innodb status' causes errors Invalid (old?)
      table or database name in logs
      
      Problem was the function filename_to_tablename in conjuction with
      partitions, since partitions intentionally uses the '#' character,
      which is not included in the filename charset.
      
      Solution was to implement the unescape filename function that
      allows the '#' character and only converts the filename from
      filename charset to system_charset_info.
modified:
  mysql-test/r/partition_innodb.result
  mysql-test/t/partition_innodb.test
  sql/mysql_priv.h
  sql/sql_table.cc
  storage/innobase/handler/ha_innodb.cc

per-file messages:
  mysql-test/r/partition_innodb.result
    Bug#32430 'show innodb status' causes errors Invalid (old?)
    table or database name in logs
    
    Updated test result.
  mysql-test/t/partition_innodb.test
    Bug#32430 'show innodb status' causes errors Invalid (old?)
    table or database name in logs
    
    Created test to generate deadlock and extract the first table name
    given in 'SHOW ENGINE INNODB STATUS' (used the perl feature in
    mysqltest).
  sql/mysql_priv.h
    Bug#32430 'show innodb status' causes errors Invalid (old?)
    table or database name in logs
    
    Added unescape_filename function
  sql/sql_table.cc
    Bug#32430 'show innodb status' causes errors Invalid (old?)
    table or database name in logs
    
    Created unescape_filename function to convert a string from
    filname charset (including the '#' character not allowed in
    that charset) to system_charset_info.
    
    This could be used for presenting info from a storage engine
    in SHOW ENGINE SE STATUS.
  storage/innobase/handler/ha_innodb.cc
    Bug#32430 'show innodb status' causes errors Invalid (old?)
    table or database name in logs
    
    Using the new unescape_filename function instead of 
    filname_to_tablename since it does not work for partitions.
=== modified file 'mysql-test/r/partition_innodb.result'
--- a/mysql-test/r/partition_innodb.result	2008-06-12 00:08:07 +0000
+++ b/mysql-test/r/partition_innodb.result	2008-07-07 10:58:15 +0000
@@ -1,3 +1,37 @@
+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
+SELECT sleep(2);
+sleep(2)
+0
+UPDATE t1 SET a = 4 WHERE a = 22;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+# First table name reported in 'SHOW ENGINE InnoDB STATUS'
+`test`.`t1#p#p0#sp#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'
--- a/mysql-test/t/partition_innodb.test	2008-06-12 00:08:07 +0000
+++ b/mysql-test/t/partition_innodb.test	2008-07-07 10:58:15 +0000
@@ -1,6 +1,63 @@
 --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;
+SEND;
+UPDATE t1 SET a = 12 WHERE a = 0;
+--echo # default connection
+connection default;
+SELECT sleep(2);
+--error ER_LOCK_DEADLOCK
+UPDATE t1 SET a = 4 WHERE a = 22;
+--exec $MYSQL -e "SHOW ENGINE InnoDB STATUS" > $MYSQLTEST_VARDIR/tmp/innodb_status.txt;
+--echo # First table name reported in 'SHOW ENGINE InnoDB STATUS'
+perl;
+open FH, "< var/tmp/innodb_status.txt" or die "Error when open";
+while (<FH>)
+{
+    next if not / of table .* trx id /;
+    my ($line) = m/of table (.*?) trx id /;
+    # must be in lower case, to be consistent on both linux
+    # and windows, since InnoDB always converts to lowercase on win.
+    print lc $line . "\n";
+}
+close FH;
+EOF
+--remove_file $MYSQLTEST_VARDIR/tmp/innodb_status.txt
+--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'
--- a/sql/mysql_priv.h	2008-05-21 10:17:29 +0000
+++ b/sql/mysql_priv.h	2008-07-07 10:58:15 +0000
@@ -2307,6 +2307,7 @@ char *fn_rext(char *name);
 #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);
+uint unescape_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/sql_table.cc'
--- a/sql/sql_table.cc	2008-06-25 11:13:03 +0000
+++ b/sql/sql_table.cc	2008-07-07 10:58:15 +0000
@@ -69,6 +69,58 @@ static void wait_for_kill_signal(THD *th
 
 
 /*
+  Translate a file name to a non escaped name.
+  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.
+
+  SYNOPSIS
+    unescape_filename()
+      from                      The file name in my_charset_filename + '#'.
+      to                OUT     The file name in system_charset_info.
+      to_length                 The size of the table name buffer.
+
+  RETURN
+    Table name length.
+*/
+
+uint unescape_filename(const char *from, char *to, uint to_length)
+{
+  uint errors;
+  uint res;
+  char *delim_p;
+  char *end_p;
+  const char *from_p;
+  char *tmp_p;
+  char tmp_name[FN_REFLEN + 6 * 4];     /* extra for #->@0023 */
+  DBUG_ENTER("unescape_filename");
+  DBUG_PRINT("enter", ("from '%s'", from));
+
+  /*
+    copy 'from' to 'tmp_name' and escape '#' to '@0023'.
+    Since '#' does not exist in filename characterset.
+  */
+  end_p= tmp_name + sizeof(tmp_name) - 1;
+  tmp_p= tmp_name;
+  from_p= from;
+  while (*from_p && (delim_p= strchr(from_p, '#')))
+  {
+    tmp_p= strnmov(tmp_p, from_p, delim_p - from_p);
+    tmp_p= strmov(tmp_p, "@0023");
+    from_p= delim_p + 1;
+  }
+  if (*from_p)
+    from_p= strnmov(tmp_p, from_p, end_p - tmp_p);
+
+  res= strconvert(&my_charset_filename, tmp_name,
+                  system_charset_info,  to, to_length, &errors);
+
+  DBUG_PRINT("exit", ("to '%s'", to));
+  DBUG_RETURN(res);
+}
+
+
+/*
   Translate a file name to a table name (WL #1324).
 
   SYNOPSIS

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2008-06-12 00:08:07 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2008-07-07 10:58:15 +0000
@@ -1271,7 +1271,7 @@ innobase_print_identifier(
 	int		q;
 
 	if (table_id) {
-		/* Decode the table name.  The filename_to_tablename()
+		/* Decode the table name.  The unescape_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
@@ -1286,7 +1286,7 @@ innobase_print_identifier(
 				memcpy(temp_name, name, namelen);
 				temp_name[namelen] = 0;
 				s = qname;
-				namelen = filename_to_tablename(temp_name,
+				namelen = unescape_filename(temp_name,
 						qname, qnamelen);
 			}
 			my_free(temp_name, MYF(0));

Thread
bzr commit into mysql-6.0 branch (mattiasj:2691) Bug#32430Mattias Jonsson7 Jul
  • Re: bzr commit into mysql-6.0 branch (mattiasj:2691) Bug#32430Sergei Golubchik10 Jul