From 53e42d9ee48ada71dc151dda0dd5119187cf5b5b Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Wed, 14 Jan 2009 18:50:51 +0400 Subject: Fix for bug#33094: Error in upgrading from 5.0 to 5.1 when table contains triggers and #41385: Crash when attempting to repair a #mysql50# upgraded table with triggers. Problem: 1. trigger code didn't assume a table name may have a "#mysql50#" prefix, that may lead to a failing ASSERT(). 2. "ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME" failed for databases with "#mysql50#" prefix if any trigger. 3. mysqlcheck --fix-table-name didn't use UTF8 as a default character set that resulted in (parsing) errors for tables with non-latin symbols in their names and definitions of triggers. Fix: 1. properly handle table/database names with "#mysql50#" prefix. 2. handle --default-character-set mysqlcheck option; if mysqlcheck is launched with --fix-table-name or --fix-db-name set default character set to UTF8 if no --default-character-set option given. Note: if given --fix-table-name or --fix-db-name option, without --default-character-set mysqlcheck option default character set is UTF8. client/mysqlcheck.c: Fix for bug#33094: Error in upgrading from 5.0 to 5.1 when table contains triggers and #41385: Crash when attempting to repair a #mysql50# upgraded table with triggers. - check and set default charset if --default-character-set option given. - set default charset to "utf8" if there's --fix-table-name or --fix-db-name and no --default-character-set. mysql-test/r/mysqlcheck.result: Fix for bug#33094: Error in upgrading from 5.0 to 5.1 when table contains triggers and #41385: Crash when attempting to repair a #mysql50# upgraded table with triggers. - test result. mysql-test/t/mysqlcheck.test: Fix for bug#33094: Error in upgrading from 5.0 to 5.1 when table contains triggers and #41385: Crash when attempting to repair a #mysql50# upgraded table with triggers. - test case. sql/mysql_priv.h: Fix for bug#33094: Error in upgrading from 5.0 to 5.1 when table contains triggers and #41385: Crash when attempting to repair a #mysql50# upgraded table with triggers. - check_n_cut_mysql50_prefix() introduced. sql/sql_table.cc: Fix for bug#33094: Error in upgrading from 5.0 to 5.1 when table contains triggers and #41385: Crash when attempting to repair a #mysql50# upgraded table with triggers. - tablename_to_filename() code split into 2 parts - check_n_cut_mysql50_prefix() introduced to cut #mysql50# prefixes, used in the trigger code as well. sql/sql_trigger.cc: Fix for bug#33094: Error in upgrading from 5.0 to 5.1 when table contains triggers and #41385: Crash when attempting to repair a #mysql50# upgraded table with triggers. - Table_triggers_list::check_n_load() - checking triggers assume a table/database name given may have "#mysql50#" prefix in some cases. - Table_triggers_list::change_table_name_in_triggers() - create .TRG file in new database directory and delete it in old one, as they may differ in case of "ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME" - Table_triggers_list::change_table_name_in_trignames() - remove stale .TRN files in #mysql50#dbname directory in case of database upgrade - Table_triggers_list::change_table_name() - allow changing trigger's database in case of its upgrading sql/sql_trigger.h: Fix for bug#33094: Error in upgrading from 5.0 to 5.1 when table contains triggers and #41385: Crash when attempting to repair a #mysql50# upgraded table with triggers. - new old_db_name parameter added in Table_triggers_list::change_table_name_in_trignames() and Table_triggers_list::change_table_name_in_triggers() --- sql/sql_table.cc | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 224cf1123e2..3ec03be72a5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -114,6 +114,30 @@ uint filename_to_tablename(const char *from, char *to, uint to_length) } +/** + Check if given string begins with "#mysql50#" prefix, cut it if so. + + @param from string to check and cut + @param to[out] buffer for result string + @param to_length its size + + @retval + 0 no prefix found + @retval + non-0 result string length +*/ + +uint check_n_cut_mysql50_prefix(const char *from, char *to, uint to_length) +{ + 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) - to); + return 0; +} + + /* Translate a table name to a file name (WL #1324). @@ -133,11 +157,8 @@ uint tablename_to_filename(const char *from, char *to, uint to_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)) - DBUG_RETURN((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH, - to_length-1) - - (from + MYSQL50_TABLE_NAME_PREFIX_LENGTH))); + if ((length= check_n_cut_mysql50_prefix(from, to, to_length))) + DBUG_RETURN(length); length= strconvert(system_charset_info, from, &my_charset_filename, to, to_length, &errors); if (check_if_legal_tablename(to) && -- cgit v1.2.1