diff --git a/client/mysqldump.c b/client/mysqldump.c index 2da4ce61689..267bb53775a 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1735,11 +1735,11 @@ static my_bool test_if_special_chars(const char *str) } /* test_if_special_chars */ - /* quote_name(name, buff, force) - Quotes char string, taking into account compatible mode + Quotes a string, if it requires quoting. To force quoting regardless + of the characters within the string, the force flag can be set to true. Args @@ -1748,8 +1748,8 @@ static my_bool test_if_special_chars(const char *str) force Flag to make it ignore 'test_if_special_chars' Returns - - buff quoted string + A pointer to the quoted string, or the original string if nothing has + changed. */ static char *quote_name(const char *name, char *buff, my_bool force) @@ -1815,6 +1815,26 @@ static char *quote_for_like(const char *name, char *buff) return buff; } +static char *quote_for_equal(const char *name, char *buff) +{ + char *to= buff; + *to++= '\''; + while (*name) + { + if (*name == '\\') + { + *to++='\\'; + } + if (*name == '\'') + *to++= '\\'; + *to++= *name++; + } + to[0]= '\''; + to[1]= 0; + return buff; + +} + /** Quote and print a string. @@ -3341,8 +3361,10 @@ static int dump_triggers_for_table(char *table_name, char *db_name) /* Get list of triggers. */ my_snprintf(query_buff, sizeof(query_buff), - "SHOW TRIGGERS LIKE %s", - quote_for_like(table_name, name_buff)); + "SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS " + "WHERE EVENT_OBJECT_SCHEMA = DATABASE() AND " + "EVENT_OBJECT_TABLE = %s", + quote_for_equal(table_name, name_buff)); if (mysql_query_with_error_report(mysql, &show_triggers_rs, query_buff)) goto done; @@ -4695,29 +4717,37 @@ static my_bool dump_all_views_in_db(char *database) /* - get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual - table name from the server for the table name given on the command line. - we do this because the table name given on the command line may be a - different case (e.g. T1 vs t1) - - RETURN - pointer to the table name - 0 if error + See get_actual_table_name. Used to retrieve the correct table name + from the database schema. */ - -static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root) +static char *get_actual_table_name_helper(const char *old_table_name, + my_bool case_sensitive, + MEM_ROOT *root) { char *name= 0; MYSQL_RES *table_res; MYSQL_ROW row; char query[50 + 2*NAME_LEN]; char show_name_buff[FN_REFLEN]; - DBUG_ENTER("get_actual_table_name"); + DBUG_ENTER("get_actual_table_name_helper"); /* Check memory for quote_for_like() */ DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff)); - my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", - quote_for_like(old_table_name, show_name_buff)); + + if (case_sensitive) + { + DBUG_PRINT("info", ("case sensitive search")); + my_snprintf(query, sizeof(query), + "SELECT table_name FROM INFORMATION_SCHEMA.TABLES " + "WHERE table_schema = DATABASE() AND table_name = %s", + quote_for_equal(old_table_name, show_name_buff)); + } + else + { + DBUG_PRINT("info", ("case insensitive search")); + my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", + quote_for_like(old_table_name, show_name_buff)); + } if (mysql_query_with_error_report(mysql, 0, query)) return NullS; @@ -4742,6 +4772,60 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root) DBUG_RETURN(name); } +/* + get_actual_table_name -- executes a SELECT .. FROM I_S.tables to check + if the table name given on the command line matches the one in the database. + If the table is not found, it falls back to a slower SHOW TABLES LIKE '%s' to + get the actual table name from the server. + + We do this because the table name given on the command line may be a + different case (e.g. T1 vs t1), but checking this takes a long time + when there are many tables present. + + RETURN + pointer to the table name + 0 if error +*/ + +static char *get_actual_table_name(const char *old_table_name, + int lower_case_table_names, + MEM_ROOT *root) +{ + char *name= 0; + DBUG_ENTER("get_actual_table_name"); + + name= get_actual_table_name_helper(old_table_name, TRUE, root); + if (!name && !lower_case_table_names) + name= get_actual_table_name_helper(old_table_name, FALSE, root); + DBUG_RETURN(name); +} + +/* + Retrieve the value for the server system variable lower_case_table_names. + + RETURN + 0 case sensitive. + > 0 case insensitive +*/ +static int get_sys_var_lower_case_table_names() +{ + int lower_case_table_names = 0; + MYSQL_RES *table_res; + MYSQL_ROW row; + const char *show_var_query = "SHOW VARIABLES LIKE 'lower_case_table_names'"; + if (mysql_query_with_error_report(mysql, &table_res, show_var_query)) + return 0; /* In case of error, assume default value of 0 */ + + if ((row= mysql_fetch_row(table_res))) + { + lower_case_table_names= atoi(row[1]); + mysql_free_result(table_res); + } + + return lower_case_table_names; +} + + static int dump_selected_tables(char *db, char **table_names, int tables) { @@ -4749,6 +4833,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) DYNAMIC_STRING lock_tables_query; MEM_ROOT root; char **dump_tables, **pos, **end; + int lower_case_table_names; DBUG_ENTER("dump_selected_tables"); if (init_dumping(db, init_dumping_tables)) @@ -4758,11 +4843,15 @@ static int dump_selected_tables(char *db, char **table_names, int tables) if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *)))) die(EX_EOM, "alloc_root failure."); + /* Figure out how to compare table names. */ + lower_case_table_names = get_sys_var_lower_case_table_names(); + init_dynamic_string_checked(&lock_tables_query, "LOCK TABLES ", 256, 1024); for (; tables > 0 ; tables-- , table_names++) { /* the table name passed on commandline may be wrong case */ - if ((*pos= get_actual_table_name(*table_names, &root))) + if ((*pos= get_actual_table_name(*table_names, lower_case_table_names, + &root))) { /* Add found table name to lock_tables_query */ if (lock_tables) @@ -5369,8 +5458,10 @@ char check_if_ignore_table(const char *table_name, char *table_type) /* Check memory for quote_for_like() */ DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff)); - my_snprintf(buff, sizeof(buff), "show table status like %s", - quote_for_like(table_name, show_name_buff)); + my_snprintf(buff, sizeof(buff), + "SELECT engine FROM INFORMATION_SCHEMA.TABLES " + "WHERE table_name = %s", + quote_for_equal(table_name, show_name_buff)); if (mysql_query_with_error_report(mysql, &res, buff)) { if (mysql_errno(mysql) != ER_PARSE_ERROR) @@ -5388,7 +5479,7 @@ char check_if_ignore_table(const char *table_name, char *table_type) mysql_free_result(res); DBUG_RETURN(result); /* assume table is ok */ } - if (!(row[1])) + if (!(row[0])) strmake(table_type, "VIEW", NAME_LEN-1); else { @@ -5398,7 +5489,7 @@ char check_if_ignore_table(const char *table_name, char *table_type) these types, but we do want to use delayed inserts in the dump if the table type is _NOT_ one of these types */ - strmake(table_type, row[1], NAME_LEN-1); + strmake(table_type, row[0], NAME_LEN-1); if (opt_delayed) { if (strcmp(table_type,"MyISAM") &&