Fix for bug #30654: mysqlcheck fails during upgrade of tables whose

names include backticks or blank

Problem: mysqlcheck doesn't escape backtick characters in the table names.

Fix: escape them.
parent 4d44d8b3
...@@ -186,6 +186,7 @@ static void dbDisconnect(char *host); ...@@ -186,6 +186,7 @@ static void dbDisconnect(char *host);
static void DBerror(MYSQL *mysql, const char *when); static void DBerror(MYSQL *mysql, const char *when);
static void safe_exit(int error); static void safe_exit(int error);
static void print_result(); static void print_result();
static uint fixed_name_length(const char *name);
static char *fix_table_name(char *dest, char *src); static char *fix_table_name(char *dest, char *src);
int what_to_do = 0; int what_to_do = 0;
...@@ -409,14 +410,14 @@ static int process_selected_tables(char *db, char **table_names, int tables) ...@@ -409,14 +410,14 @@ static int process_selected_tables(char *db, char **table_names, int tables)
{ {
/* /*
We need table list in form `a`, `b`, `c` We need table list in form `a`, `b`, `c`
that's why we need 4 more chars added to to each table name that's why we need 2 more chars added to to each table name
space is for more readable output in logs and in case of error space is for more readable output in logs and in case of error
*/ */
char *table_names_comma_sep, *end; char *table_names_comma_sep, *end;
int i, tot_length = 0; int i, tot_length = 0;
for (i = 0; i < tables; i++) for (i = 0; i < tables; i++)
tot_length += strlen(*(table_names + i)) + 4; tot_length+= fixed_name_length(*(table_names + i)) + 2;
if (!(table_names_comma_sep = (char *) if (!(table_names_comma_sep = (char *)
my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME)))) my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
...@@ -434,23 +435,46 @@ static int process_selected_tables(char *db, char **table_names, int tables) ...@@ -434,23 +435,46 @@ static int process_selected_tables(char *db, char **table_names, int tables)
} }
else else
for (; tables > 0; tables--, table_names++) for (; tables > 0; tables--, table_names++)
handle_request_for_tables(*table_names, strlen(*table_names)); handle_request_for_tables(*table_names, fixed_name_length(*table_names));
return 0; return 0;
} /* process_selected_tables */ } /* process_selected_tables */
static char *fix_table_name(char *dest, char *src) static uint fixed_name_length(const char *name)
{ {
char *db_sep; const char *p;
uint extra_length= 2; /* count the first/last backticks */
for (p= name; *p; p++)
{
if (*p == '`')
extra_length++;
else if (*p == '.')
extra_length+= 2;
}
return (p - name) + extra_length;
}
static char *fix_table_name(char *dest, char *src)
{
*dest++= '`'; *dest++= '`';
if ((db_sep= strchr(src, '.'))) for (; *src; src++)
{ {
dest= strmake(dest, src, (uint) (db_sep - src)); switch (*src) {
dest= strmov(dest, "`.`"); case '.': /* add backticks around '.' */
src= db_sep + 1; *dest++= '`';
*dest++= '.';
*dest++= '`';
break;
case '`': /* escape backtick character */
*dest++= '`';
/* fall through */
default:
*dest++= *src;
}
} }
dest= strxmov(dest, src, "`", NullS); *dest++= '`';
return dest; return dest;
} }
...@@ -471,7 +495,7 @@ static int process_all_tables_in_db(char *database) ...@@ -471,7 +495,7 @@ static int process_all_tables_in_db(char *database)
{ {
/* /*
We need table list in form `a`, `b`, `c` We need table list in form `a`, `b`, `c`
that's why we need 4 more chars added to to each table name that's why we need 2 more chars added to to each table name
space is for more readable output in logs and in case of error space is for more readable output in logs and in case of error
*/ */
...@@ -479,7 +503,7 @@ static int process_all_tables_in_db(char *database) ...@@ -479,7 +503,7 @@ static int process_all_tables_in_db(char *database)
uint tot_length = 0; uint tot_length = 0;
while ((row = mysql_fetch_row(res))) while ((row = mysql_fetch_row(res)))
tot_length += strlen(row[0]) + 4; tot_length+= fixed_name_length(row[0]) + 2;
mysql_data_seek(res, 0); mysql_data_seek(res, 0);
if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME)))) if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
...@@ -507,7 +531,7 @@ static int process_all_tables_in_db(char *database) ...@@ -507,7 +531,7 @@ static int process_all_tables_in_db(char *database)
/* Skip tables with an engine of NULL (probably a view). */ /* Skip tables with an engine of NULL (probably a view). */
if (row[1]) if (row[1])
{ {
handle_request_for_tables(row[0], strlen(row[0])); handle_request_for_tables(row[0], fixed_name_length(row[0]));
} }
} }
mysql_free_result(res); mysql_free_result(res);
...@@ -741,7 +765,7 @@ int main(int argc, char **argv) ...@@ -741,7 +765,7 @@ int main(int argc, char **argv)
for (i = 0; i < tables4repair.elements ; i++) for (i = 0; i < tables4repair.elements ; i++)
{ {
char *name= (char*) dynamic_array_ptr(&tables4repair, i); char *name= (char*) dynamic_array_ptr(&tables4repair, i);
handle_request_for_tables(name, strlen(name)); handle_request_for_tables(name, fixed_name_length(name));
} }
} }
end: end:
......
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1, `t``1`, `t 1`;
drop view if exists v1; drop view if exists v1;
drop database if exists client_test_db; drop database if exists client_test_db;
mysql.columns_priv OK mysql.columns_priv OK
...@@ -41,4 +41,9 @@ test.t1 OK ...@@ -41,4 +41,9 @@ test.t1 OK
test.t1 OK test.t1 OK
drop view v1; drop view v1;
drop table t1; drop table t1;
create table `t``1`(a int);
create table `t 1`(a int);
test.t 1 OK
test.t`1 OK
drop table `t``1`, `t 1`;
End of 5.0 tests End of 5.0 tests
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# #
--disable_warnings --disable_warnings
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1, `t``1`, `t 1`;
drop view if exists v1; drop view if exists v1;
drop database if exists client_test_db; drop database if exists client_test_db;
--enable_warnings --enable_warnings
...@@ -31,4 +31,13 @@ create view v1 as select * from t1; ...@@ -31,4 +31,13 @@ create view v1 as select * from t1;
drop view v1; drop view v1;
drop table t1; drop table t1;
#
# Bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks
#
create table `t``1`(a int);
create table `t 1`(a int);
--replace_result 'Table is already up to date' OK
--exec $MYSQL_CHECK --databases test
drop table `t``1`, `t 1`;
--echo End of 5.0 tests --echo End of 5.0 tests
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment