From 7faf69dd82550d921761c142aefeb93c93c4f44b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 10 Jan 2012 13:33:45 +0530 Subject: [PATCH] BUG#11760384 - 52792: mysqldump in XML mode does not dump routines. mysqldump in xml mode did not dump routines, events or triggers. This patch fixes this issue by fixing the if conditions that disallowed the dump of above mentioned objects in xml mode, and added the required code to enable dump in xml format. --- client/mysqldump.c | 461 ++++++++++++++++++++++++---------- mysql-test/r/mysqldump.result | 439 ++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 112 +++++++++ 3 files changed, 884 insertions(+), 128 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 31d4ba40109..27a593ff592 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -76,6 +76,9 @@ /* Size of buffer for dump's select query */ #define QUERY_LENGTH 1536 +/* Size of comment buffer. */ +#define COMMENT_LENGTH 2048 + /* ignore table flags */ #define IGNORE_NONE 0x00 /* no ignore */ #define IGNORE_DATA 0x01 /* don't dump data for this table */ @@ -102,7 +105,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_complete_insert= 0, opt_drop_database= 0, opt_replace_into= 0, opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1, - opt_events= 0, + opt_events= 0, opt_comments_used= 0, opt_alltspcs=0, opt_notspcs= 0; static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0; static ulong opt_max_allowed_packet, opt_net_buffer_length; @@ -509,6 +512,8 @@ static int dump_all_tablespaces(); static int dump_tablespaces_for_tables(char *db, char **table_names, int tables); static int dump_tablespaces_for_databases(char** databases); static int dump_tablespaces(char* ts_where); +static void print_comment(FILE *sql_file, my_bool is_error, const char *format, + ...); #include @@ -606,19 +611,19 @@ static void write_header(FILE *sql_file, char *db_name) } else if (!opt_compact) { - if (opt_comments) - { - fprintf(sql_file, - "-- MySQL dump %s Distrib %s, for %s (%s)\n--\n", - DUMP_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); - fprintf(sql_file, "-- Host: %s Database: %s\n", - current_host ? current_host : "localhost", db_name ? db_name : - ""); - fputs("-- ------------------------------------------------------\n", - sql_file); - fprintf(sql_file, "-- Server version\t%s\n", - mysql_get_server_info(&mysql_connection)); - } + print_comment(sql_file, 0, + "-- MySQL dump %s Distrib %s, for %s (%s)\n--\n", + DUMP_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE, + MACHINE_TYPE); + print_comment(sql_file, 0, "-- Host: %s Database: %s\n", + current_host ? current_host : "localhost", + db_name ? db_name : ""); + print_comment(sql_file, 0, + "-- ------------------------------------------------------\n" + ); + print_comment(sql_file, 0, "-- Server version\t%s\n", + mysql_get_server_info(&mysql_connection)); + if (opt_set_charset) fprintf(sql_file, "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;" @@ -676,18 +681,16 @@ static void write_footer(FILE *sql_file) fprintf(sql_file, "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n"); fputs("\n", sql_file); - if (opt_comments) + + if (opt_dump_date) { - if (opt_dump_date) - { - char time_str[20]; - get_date(time_str, GETDATE_DATE_TIME, 0); - fprintf(sql_file, "-- Dump completed on %s\n", - time_str); - } - else - fprintf(sql_file, "-- Dump completed\n"); + char time_str[20]; + get_date(time_str, GETDATE_DATE_TIME, 0); + print_comment(sql_file, 0, "-- Dump completed on %s\n", time_str); } + else + print_comment(sql_file, 0, "-- Dump completed\n"); + check_io(sql_file); } } /* write_footer */ @@ -772,6 +775,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), extended_insert= opt_drop= opt_lock= opt_disable_keys= opt_autocommit= opt_create_db= 0; break; + case 'i': + opt_comments_used= 1; + break; case 'I': case '?': usage(); @@ -798,11 +804,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_disable_keys= lock_tables= opt_set_charset= 0; break; case (int) OPT_COMPACT: - if (opt_compact) - { - opt_comments= opt_drop= opt_disable_keys= opt_lock= 0; - opt_set_charset= 0; - } + if (opt_compact) + { + opt_comments= opt_drop= opt_disable_keys= opt_lock= 0; + opt_set_charset= 0; + } + break; case (int) OPT_TABLES: opt_databases=0; break; @@ -1660,20 +1667,20 @@ static char *quote_for_like(const char *name, char *buff) } -/* +/** Quote and print a string. - SYNOPSIS - print_quoted_xml() - xml_file - output file - str - string to print - len - its length + @param xml_file - Output file. + @param str - String to print. + @param len - Its length. + @param is_attribute_name - A check for attribute name or value. - DESCRIPTION + @description Quote '<' '>' '&' '\"' chars and print a string to the xml_file. */ -static void print_quoted_xml(FILE *xml_file, const char *str, ulong len) +static void print_quoted_xml(FILE *xml_file, const char *str, ulong len, + my_bool is_attribute_name) { const char *end; @@ -1692,6 +1699,14 @@ static void print_quoted_xml(FILE *xml_file, const char *str, ulong len) case '\"': fputs(""", xml_file); break; + case ' ': + /* Attribute names cannot contain spaces. */ + if (is_attribute_name) + { + fputs("_", xml_file); + break; + } + /* fall through */ default: fputc(*str, xml_file); break; @@ -1752,7 +1767,7 @@ static void print_xml_tag(FILE * xml_file, const char* sbeg, fputs(attribute_name, xml_file); fputc('\"', xml_file); - print_quoted_xml(xml_file, attribute_value, strlen(attribute_value)); + print_quoted_xml(xml_file, attribute_value, strlen(attribute_value), 0); fputc('\"', xml_file); attribute_name= va_arg(arg_list, char *); @@ -1792,13 +1807,52 @@ static void print_xml_null_tag(FILE * xml_file, const char* sbeg, fputs("<", xml_file); fputs(stag_atr, xml_file); fputs("\"", xml_file); - print_quoted_xml(xml_file, sval, strlen(sval)); + print_quoted_xml(xml_file, sval, strlen(sval), 0); fputs("\" xsi:nil=\"true\" />", xml_file); fputs(line_end, xml_file); check_io(xml_file); } +/** + Print xml CDATA section. + + @param xml_file - output file + @param str - string to print + @param len - length of the string + + @note + This function also takes care of the presence of '[[>' + string in the str. If found, the CDATA section is broken + into two CDATA sections, and ]]. +*/ + +static void print_xml_cdata(FILE *xml_file, const char *str, ulong len) +{ + const char *end; + + fputs("')) + { + fputs("]]]]>", xml_file); + str += 2; + continue; + } + /* fall through */ + default: + fputc(*str, xml_file); + break; + } + } + fputs("\n]]>\n", xml_file); + check_io(xml_file); +} + + /* Print xml tag with many attributes. @@ -1808,6 +1862,7 @@ static void print_xml_null_tag(FILE * xml_file, const char* sbeg, row_name - xml tag name tableRes - query result row - result row + str_create - create statement header string DESCRIPTION Print tag with many attribute to the xml_file. Format is: @@ -1817,9 +1872,13 @@ static void print_xml_null_tag(FILE * xml_file, const char* sbeg, */ static void print_xml_row(FILE *xml_file, const char *row_name, - MYSQL_RES *tableRes, MYSQL_ROW *row) + MYSQL_RES *tableRes, MYSQL_ROW *row, + const char *str_create) { uint i; + my_bool body_found= 0; + char *create_stmt_ptr; + ulong create_stmt_len= 0; MYSQL_FIELD *field; ulong *lengths= mysql_fetch_lengths(tableRes); @@ -1830,19 +1889,109 @@ static void print_xml_row(FILE *xml_file, const char *row_name, { if ((*row)[i]) { - fputc(' ', xml_file); - print_quoted_xml(xml_file, field->name, field->name_length); - fputs("=\"", xml_file); - print_quoted_xml(xml_file, (*row)[i], lengths[i]); - fputc('"', xml_file); - check_io(xml_file); + /* For 'create' statements, dump using CDATA. */ + if ((str_create) && (strcmp(str_create, field->name) == 0)) + { + create_stmt_ptr= (*row)[i]; + create_stmt_len= lengths[i]; + body_found= 1; + } + else + { + fputc(' ', xml_file); + print_quoted_xml(xml_file, field->name, field->name_length, 1); + fputs("=\"", xml_file); + print_quoted_xml(xml_file, (*row)[i], lengths[i], 0); + fputc('"', xml_file); + check_io(xml_file); + } } } - fputs(" />\n", xml_file); + + if (create_stmt_len) + { + DBUG_ASSERT(body_found); + fputs(">\n", xml_file); + print_xml_cdata(xml_file, create_stmt_ptr, create_stmt_len); + fprintf(xml_file, "\t\t\n", row_name); + } + else + fputs(" />\n", xml_file); + check_io(xml_file); } +/** + Print xml comments. + + @param xml_file - output file + @param len - length of comment message + @param comment_string - comment message + + @description + Print the comment message in the format: + "\n" + + @note + Any occurrence of continuous hyphens will be + squeezed to a single hyphen. +*/ + +static void print_xml_comment(FILE *xml_file, ulong len, + const char *comment_string) +{ + const char* end; + + fputs("\n", xml_file); + check_io(xml_file); +} + + + +/* A common printing function for xml and non-xml modes. */ + +static void print_comment(FILE *sql_file, my_bool is_error, const char *format, + ...) +{ + static char comment_buff[COMMENT_LENGTH]; + va_list args; + + /* If its an error message, print it ignoring opt_comments. */ + if (!is_error && !opt_comments) + return; + + va_start(args, format); + my_vsnprintf(comment_buff, COMMENT_LENGTH, format, args); + va_end(args); + + if (!opt_xml) + { + fputs(comment_buff, sql_file); + check_io(sql_file); + return; + } + + print_xml_comment(sql_file, strlen(comment_buff), comment_buff); +} + + /* create_delimiter Generate a new (null-terminated) string that does not exist in query @@ -1909,8 +2058,8 @@ static uint dump_events_for_db(char *db) mysql_real_escape_string(mysql, db_name_buff, db, strlen(db)); /* nice comments */ - if (opt_comments) - fprintf(sql_file, "\n--\n-- Dumping events for database '%s'\n--\n", db); + print_comment(sql_file, 0, + "\n--\n-- Dumping events for database '%s'\n--\n", db); /* not using "mysql_query_with_error_report" because we may have not @@ -1925,12 +2074,17 @@ static uint dump_events_for_db(char *db) strcpy(delimiter, ";"); if (mysql_num_rows(event_list_res) > 0) { - fprintf(sql_file, "/*!50106 SET @save_time_zone= @@TIME_ZONE */ ;\n"); + if (opt_xml) + fputs("\t\n", sql_file); + else + { + fprintf(sql_file, "/*!50106 SET @save_time_zone= @@TIME_ZONE */ ;\n"); - /* Get database collation. */ + /* Get database collation. */ - if (fetch_db_collation(db_name_buff, db_cl_name, sizeof (db_cl_name))) - DBUG_RETURN(1); + if (fetch_db_collation(db_name_buff, db_cl_name, sizeof (db_cl_name))) + DBUG_RETURN(1); + } if (switch_character_set_results(mysql, "binary")) DBUG_RETURN(1); @@ -1947,6 +2101,13 @@ static uint dump_events_for_db(char *db) while ((row= mysql_fetch_row(event_res)) != NULL) { + if (opt_xml) + { + print_xml_row(sql_file, "event", event_res, &row, + "Create Event"); + continue; + } + /* if the user has EXECUTE privilege he can see event names, but not the event body! @@ -2025,8 +2186,16 @@ static uint dump_events_for_db(char *db) mysql_free_result(event_res); } /* end of list of events */ - fprintf(sql_file, "DELIMITER ;\n"); - fprintf(sql_file, "/*!50106 SET TIME_ZONE= @save_time_zone */ ;\n"); + if (opt_xml) + { + fputs("\t\n", sql_file); + check_io(sql_file); + } + else + { + fprintf(sql_file, "DELIMITER ;\n"); + fprintf(sql_file, "/*!50106 SET TIME_ZONE= @save_time_zone */ ;\n"); + } if (switch_character_set_results(mysql, default_charset)) DBUG_RETURN(1); @@ -2080,6 +2249,7 @@ static uint dump_routines_for_db(char *db) const char *routine_type[]= {"FUNCTION", "PROCEDURE"}; char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3]; char *routine_name; + char *query_str; int i; FILE *sql_file= md_result_file; MYSQL_RES *routine_res, *routine_list_res; @@ -2094,8 +2264,8 @@ static uint dump_routines_for_db(char *db) mysql_real_escape_string(mysql, db_name_buff, db, strlen(db)); /* nice comments */ - if (opt_comments) - fprintf(sql_file, "\n--\n-- Dumping routines for database '%s'\n--\n", db); + print_comment(sql_file, 0, + "\n--\n-- Dumping routines for database '%s'\n--\n", db); /* not using "mysql_query_with_error_report" because we may have not @@ -2112,6 +2282,9 @@ static uint dump_routines_for_db(char *db) if (switch_character_set_results(mysql, "binary")) DBUG_RETURN(1); + if (opt_xml) + fputs("\t\n", sql_file); + /* 0, retrieve and dump functions, 1, procedures */ for (i= 0; i <= 1; i++) { @@ -2147,13 +2320,25 @@ static uint dump_routines_for_db(char *db) row[2] ? (int) strlen(row[2]) : 0)); if (row[2] == NULL) { - fprintf(sql_file, "\n-- insufficient privileges to %s\n", query_buff); - fprintf(sql_file, "-- does %s have permissions on mysql.proc?\n\n", current_user); + print_comment(sql_file, 1, "\n-- insufficient privileges to %s\n", + query_buff); + print_comment(sql_file, 1, + "-- does %s have permissions on mysql.proc?\n\n", + current_user); maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff); } else if (strlen(row[2])) { - char *query_str; + if (opt_xml) + { + if (i) // Procedures. + print_xml_row(sql_file, "routine", routine_res, &row, + "Create Procedure"); + else // Functions. + print_xml_row(sql_file, "routine", routine_res, &row, + "Create Function"); + continue; + } if (opt_drop) fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n", routine_type[i], routine_name); @@ -2224,6 +2409,12 @@ static uint dump_routines_for_db(char *db) mysql_free_result(routine_list_res); } /* end of for i (0 .. 1) */ + if (opt_xml) + { + fputs("\t\n", sql_file); + check_io(sql_file); + } + if (switch_character_set_results(mysql, default_charset)) DBUG_RETURN(1); @@ -2336,16 +2527,16 @@ static uint get_table_structure(char *table, char *db, char *table_type, write_header(sql_file, db); } - if (!opt_xml && opt_comments) - { + if (strcmp (table_type, "VIEW") == 0) /* view */ - fprintf(sql_file, "\n--\n-- Temporary table structure for view %s\n--\n\n", - result_table); + print_comment(sql_file, 0, + "\n--\n-- Temporary table structure for view %s\n--\n\n", + result_table); else - fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", - result_table); - check_io(sql_file); - } + print_comment(sql_file, 0, + "\n--\n-- Table structure for table %s\n--\n\n", + result_table); + if (opt_drop) { /* @@ -2546,9 +2737,10 @@ static uint get_table_structure(char *table, char *db, char *table_type, DBUG_RETURN(0); write_header(sql_file, db); } - if (!opt_xml && opt_comments) - fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", - result_table); + + print_comment(sql_file, 0, + "\n--\n-- Table structure for table %s\n--\n\n", + result_table); if (opt_drop) fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table); if (!opt_xml) @@ -2599,7 +2791,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, { if (opt_xml) { - print_xml_row(sql_file, "field", result, &row); + print_xml_row(sql_file, "field", result, &row, NullS); continue; } @@ -2671,7 +2863,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, { if (opt_xml) { - print_xml_row(sql_file, "key", result, &row); + print_xml_row(sql_file, "key", result, &row, NullS); continue; } @@ -2730,7 +2922,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, else { if (opt_xml) - print_xml_row(sql_file, "options", result, &row); + print_xml_row(sql_file, "options", result, &row, NullS); else { fputs("/*!",sql_file); @@ -2774,9 +2966,19 @@ static void dump_trigger_old(FILE *sql_file, MYSQL_RES *show_triggers_rs, char *quoted_table_name= quote_name(table_name, quoted_table_name_buf, 1); char name_buff[NAME_LEN * 4 + 3]; + const char *xml_msg= "\nWarning! mysqldump being run against old server " + "that does not\nsupport 'SHOW CREATE TRIGGERS' " + "statement. Skipping..\n"; DBUG_ENTER("dump_trigger_old"); + if (opt_xml) + { + print_xml_comment(sql_file, strlen(xml_msg), xml_msg); + check_io(sql_file); + DBUG_VOID_RETURN; + } + fprintf(sql_file, "--\n" "-- WARNING: old server version. " @@ -2840,13 +3042,22 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs, const char *db_cl_name) { MYSQL_ROW row; + char *query_str; int db_cl_altered= FALSE; DBUG_ENTER("dump_trigger"); while ((row= mysql_fetch_row(show_create_trigger_rs))) { - char *query_str= cover_definer_clause_in_trigger(row[2], strlen(row[2])); + if (opt_xml) + { + print_xml_row(sql_file, "trigger", show_create_trigger_rs, &row, + "SQL Original Statement"); + check_io(sql_file); + continue; + } + + query_str= cover_definer_clause_in_trigger(row[2], strlen(row[2])); if (switch_db_collation(sql_file, db_name, ";", @@ -2936,6 +3147,13 @@ static int dump_triggers_for_table(char *table_name, char *db_name) /* Dump triggers. */ + if (! mysql_num_rows(show_triggers_rs)) + goto skip; + + if (opt_xml) + print_xml_tag(sql_file, "\t", "\n", "triggers", "name=", + table_name, NullS); + while ((row= mysql_fetch_row(show_triggers_rs))) { @@ -2968,6 +3186,13 @@ static int dump_triggers_for_table(char *table_name, char *db_name) } + if (opt_xml) + { + fputs("\t\n", sql_file); + check_io(sql_file); + } + +skip: mysql_free_result(show_triggers_rs); if (switch_character_set_results(mysql, default_charset)) @@ -3216,34 +3441,24 @@ static void dump_table(char *table, char *db) } else { - if (!opt_xml && opt_comments) - { - fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n", - result_table); - check_io(md_result_file); - } + print_comment(md_result_file, 0, + "\n--\n-- Dumping data for table %s\n--\n", + result_table); dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM "); dynstr_append_checked(&query_string, result_table); if (where) { - if (!opt_xml && opt_comments) - { - fprintf(md_result_file, "-- WHERE: %s\n", where); - check_io(md_result_file); - } - + print_comment(md_result_file, 0, "-- WHERE: %s\n", where); + dynstr_append_checked(&query_string, " WHERE "); dynstr_append_checked(&query_string, where); } if (order_by) { - if (!opt_xml && opt_comments) - { - fprintf(md_result_file, "-- ORDER BY: %s\n", order_by); - check_io(md_result_file); - } + print_comment(md_result_file, 0, "-- ORDER BY: %s\n", order_by); + dynstr_append_checked(&query_string, " ORDER BY "); dynstr_append_checked(&query_string, order_by); } @@ -3439,7 +3654,7 @@ static void dump_table(char *table, char *db) { print_xml_tag(md_result_file, "\t\t", "", "field", "name=", field->name, NullS); - print_quoted_xml(md_result_file, row[i], length); + print_quoted_xml(md_result_file, row[i], length, 0); } fputs("\n", md_result_file); } @@ -3743,11 +3958,9 @@ static int dump_tablespaces(char* ts_where) first= 1; if (first) { - if (!opt_xml && opt_comments) - { - fprintf(md_result_file,"\n--\n-- Logfile group: %s\n--\n", row[0]); - check_io(md_result_file); - } + print_comment(md_result_file, 0, "\n--\n-- Logfile group: %s\n--\n", + row[0]); + fprintf(md_result_file, "\nCREATE"); } else @@ -3815,11 +4028,7 @@ static int dump_tablespaces(char* ts_where) first= 1; if (first) { - if (!opt_xml && opt_comments) - { - fprintf(md_result_file,"\n--\n-- Tablespace: %s\n--\n", row[0]); - check_io(md_result_file); - } + print_comment(md_result_file, 0, "\n--\n-- Tablespace: %s\n--\n", row[0]); fprintf(md_result_file, "\nCREATE"); } else @@ -4009,11 +4218,9 @@ static int init_dumping(char *database, int init_func(char*)) */ char quoted_database_buf[NAME_LEN*2+3]; char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); - if (opt_comments) - { - fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase); - check_io(md_result_file); - } + + print_comment(md_result_file, 0, + "\n--\n-- Current Database: %s\n--\n", qdatabase); /* Call the view or table specific function */ init_func(qdatabase); @@ -4087,8 +4294,7 @@ static int dump_all_tables_in_db(char *database) dump_table(table,database); my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); order_by= 0; - if (opt_dump_triggers && ! opt_xml && - mysql_get_server_version(mysql) >= 50009) + if (opt_dump_triggers && mysql_get_server_version(mysql) >= 50009) { if (dump_triggers_for_table(table, database)) { @@ -4099,14 +4305,12 @@ static int dump_all_tables_in_db(char *database) } } } - if (opt_events && !opt_xml && - mysql_get_server_version(mysql) >= 50106) + if (opt_events && mysql_get_server_version(mysql) >= 50106) { DBUG_PRINT("info", ("Dumping events for database %s", database)); dump_events_for_db(database); } - if (opt_routines && !opt_xml && - mysql_get_server_version(mysql) >= 50009) + if (opt_routines && mysql_get_server_version(mysql) >= 50009) { DBUG_PRINT("info", ("Dumping routines for database %s", database)); dump_routines_for_db(database); @@ -4341,15 +4545,13 @@ static int dump_selected_tables(char *db, char **table_names, int tables) for (pos= dump_tables; pos < end; pos++) get_view_structure(*pos, db); } - if (opt_events && !opt_xml && - mysql_get_server_version(mysql) >= 50106) + if (opt_events && mysql_get_server_version(mysql) >= 50106) { DBUG_PRINT("info", ("Dumping events for database %s", db)); dump_events_for_db(db); } /* obtain dump of routines (procs/functions) */ - if (opt_routines && !opt_xml && - mysql_get_server_version(mysql) >= 50009) + if (opt_routines && mysql_get_server_version(mysql) >= 50009) { DBUG_PRINT("info", ("Dumping routines for database %s", db)); dump_routines_for_db(db); @@ -4384,10 +4586,9 @@ static int do_show_master_status(MYSQL *mysql_con) if (row && row[0] && row[1]) { /* SHOW MASTER STATUS reports file and position */ - if (opt_comments) - fprintf(md_result_file, - "\n--\n-- Position to start replication or point-in-time " - "recovery from\n--\n\n"); + print_comment(md_result_file, 0, + "\n--\n-- Position to start replication or point-in-time " + "recovery from\n--\n\n"); fprintf(md_result_file, "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", comment_prefix, row[0], row[1]); @@ -4850,12 +5051,10 @@ static my_bool get_view_structure(char *table, char* db) write_header(sql_file, db); } - if (!opt_xml && opt_comments) - { - fprintf(sql_file, "\n--\n-- Final view structure for view %s\n--\n\n", - result_table); - check_io(sql_file); - } + print_comment(sql_file, 0, + "\n--\n-- Final view structure for view %s\n--\n\n", + result_table); + /* Table might not exist if this view was dumped with --tab. */ fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n", opt_quoted_table); if (opt_drop) @@ -5052,6 +5251,12 @@ int main(int argc, char **argv) exit(exit_code); } + /* + Disable comments in xml mode if 'comments' option is not explicitly used. + */ + if (opt_xml && !opt_comments_used) + opt_comments= 0; + if (log_error_file) { if(!(stderror_file= freopen(log_error_file, "a+", stderr))) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index a337c0384f6..1d4a5783c3f 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -4628,5 +4628,444 @@ ALTER DATABASE `test-database` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; DROP DATABASE `test-database`; USE `test`; # +# BUG#11760384 : 52792: mysqldump in XML mode does not dump routines. +# +CREATE DATABASE BUG52792; +USE BUG52792; +CREATE TABLE t1 (c1 INT, c2 VARCHAR(20)); +CREATE TABLE t2 (c1 INT); +INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc'); +INSERT INTO t2 VALUES (1),(2),(3); +# Stored Procedures. +CREATE PROCEDURE simpleproc1 (OUT param1 INT) +BEGIN +SELECT COUNT(*) INTO param1 FROM t1; +END// +CREATE PROCEDURE simpleproc2 (OUT param1 INT) +BEGIN +SELECT COUNT(*) INTO param1 FROM t2; +END// +# Events. +CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE BUG52792; +CREATE EVENT e2 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE BUG52792; +# Functions. +CREATE FUNCTION `hello1` (s CHAR(20)) +RETURNS CHAR(50) DETERMINISTIC +RETURN CONCAT('Hello, ' ,s ,'!'); +CREATE FUNCTION `hello2` (s CHAR(20)) +RETURNS CHAR(50) DETERMINISTIC +RETURN CONCAT(']]>, ' , s ,'!'); +# Triggers. +CREATE TRIGGER trig1 BEFORE INSERT ON t2 +FOR EACH ROW BEGIN +INSERT INTO t2 VALUES(1); +END; +| +CREATE TRIGGER trig2 AFTER INSERT ON t2 +FOR EACH ROW BEGIN +INSERT INTO t2 VALUES(1, ']]>'); +INSERT INTO t2 VALUES(2, ''); +INSERT INTO t2 VALUES(3, ' & \ " _'); +END; +| +# Views +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE VIEW v2 AS SELECT * FROM t2; + +# Dumping BUG52792 database in xml format. + +# Running 'replace_regex on timestamp' + + + + + + + + + + + 1 + aaa + + + 2 + bbb + + + 3 + ccc + + + + + + + + + 1 + + + 2 + + + 3 + + + + + + + +'); +INSERT INTO t2 VALUES(2, ''); +INSERT INTO t2 VALUES(3, ' & \ " _'); +END +]]> + + + + + + + + + + + + + + + + + + + + + + + + +, ' , s ,'!') +]]> + + + + + + + + + + + +# Dumping BUG52792 database in xml format with comments. + +# Running 'replace_regex on timestamp' + + + + + + + + + + + + + 1 + aaa + + + 2 + bbb + + + 3 + ccc + + + + + + + + + + + 1 + + + 2 + + + 3 + + + + + + + +'); +INSERT INTO t2 VALUES(2, ''); +INSERT INTO t2 VALUES(3, ' & \ " _'); +END +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + +, ' , s ,'!') +]]> + + + + + + + + + + + +# Test to check 'Insufficient privileges' error. + +GRANT ALL PRIVILEGES ON BUG52792.* TO user1; +# Running 'replace_regex on timestamp' + + + + + + + + + + + 1 + aaa + + + 2 + bbb + + + 3 + ccc + + + + + + + + + 1 + + + 2 + + + 3 + + + + + + + +'); +INSERT INTO t2 VALUES(2, ''); +INSERT INTO t2 VALUES(3, ' & \ " _'); +END +]]> + + + + + + + + + + + + + + + + + + + + + + +DROP USER user1; +DROP DATABASE BUG52792; +# UTF-8 +CREATE DATABASE BUG52792; +USE BUG52792; +SET NAMES utf8; +CREATE FUNCTION `straße` ( c1 CHAR(20)) +RETURNS CHAR(50) DETERMINISTIC +RETURN CONCAT(']]>, ', s, '!'); + + + + + +, ', s, '!') +]]> + + + + +DROP DATABASE BUG52792; +USE test; +# # End of 5.1 tests # diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 8ecf8187ff9..20c788e3b9a 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -2196,6 +2196,118 @@ DROP DATABASE `test-database`; # Switching back to test database. USE `test`; +--echo # +--echo # BUG#11760384 : 52792: mysqldump in XML mode does not dump routines. +--echo # +CREATE DATABASE BUG52792; +USE BUG52792; +CREATE TABLE t1 (c1 INT, c2 VARCHAR(20)); +CREATE TABLE t2 (c1 INT); +INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc'); +INSERT INTO t2 VALUES (1),(2),(3); + +--echo # Stored Procedures. + +DELIMITER //; +CREATE PROCEDURE simpleproc1 (OUT param1 INT) +BEGIN + SELECT COUNT(*) INTO param1 FROM t1; +END// +DELIMITER ;// + +DELIMITER //; +CREATE PROCEDURE simpleproc2 (OUT param1 INT) +BEGIN + SELECT COUNT(*) INTO param1 FROM t2; +END// +DELIMITER ;// + +--echo # Events. + +CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE BUG52792; +CREATE EVENT e2 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE BUG52792; + +--echo # Functions. + +CREATE FUNCTION `hello1` (s CHAR(20)) + RETURNS CHAR(50) DETERMINISTIC +RETURN CONCAT('Hello, ' ,s ,'!'); + +CREATE FUNCTION `hello2` (s CHAR(20)) + RETURNS CHAR(50) DETERMINISTIC +RETURN CONCAT(']]>, ' , s ,'!'); + +--echo # Triggers. + +DELIMITER |; +CREATE TRIGGER trig1 BEFORE INSERT ON t2 + FOR EACH ROW BEGIN + INSERT INTO t2 VALUES(1); +END; +| +DELIMITER ;| + +DELIMITER |; +CREATE TRIGGER trig2 AFTER INSERT ON t2 + FOR EACH ROW BEGIN + INSERT INTO t2 VALUES(1, ']]>'); + INSERT INTO t2 VALUES(2, ''); + INSERT INTO t2 VALUES(3, ' & \ " _'); +END; +| +DELIMITER ;| + +--echo # Views + +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE VIEW v2 AS SELECT * FROM t2; +--echo +--echo # Dumping BUG52792 database in xml format. +--echo +--echo # Running 'replace_regex on timestamp' +--replace_regex /[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/--TIME--/ +--exec $MYSQL_DUMP --user=root --compact -R -E --triggers -X BUG52792 +--echo +--echo # Dumping BUG52792 database in xml format with comments. +--echo +--echo # Running 'replace_regex on timestamp' +--replace_regex /[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/--TIME--/ +--exec $MYSQL_DUMP --comments --user=root -R -E --triggers -X BUG52792 + +--echo +--echo # Test to check 'Insufficient privileges' error. +--echo + +GRANT ALL PRIVILEGES ON BUG52792.* TO user1; + +connect (conn_1, localhost, user1, , BUG52792, $MASTER_MYPORT, $MASTER_MYSOCK); +connection conn_1; + +--echo # Running 'replace_regex on timestamp' +--replace_regex /[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/--TIME--/ +--error 2 +--exec $MYSQL_DUMP --user=user1 -R -E --triggers -X BUG52792 + +connection default; +disconnect conn_1; + +DROP USER user1; +DROP DATABASE BUG52792; +--echo # UTF-8 +CREATE DATABASE BUG52792; +USE BUG52792; +SET NAMES utf8; +CREATE FUNCTION `straße` ( c1 CHAR(20)) + RETURNS CHAR(50) DETERMINISTIC +RETURN CONCAT(']]>, ', s, '!'); + +--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 -R -X BUG52792 + +DROP DATABASE BUG52792; + +USE test; + --echo # --echo # End of 5.1 tests --echo #