diff options
Diffstat (limited to 'client/mysqldump.c')
-rw-r--r-- | client/mysqldump.c | 763 |
1 files changed, 497 insertions, 266 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c index 27582260cb9..c20d4947185 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -12,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* mysqldump.c - Dump a tables contents and format to an ASCII file @@ -52,7 +52,8 @@ #include "mysql.h" #include "mysql_version.h" #include "mysqld_error.h" -#include "../sql/ha_ndbcluster_tables.h" + +#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ /* Exit codes */ @@ -85,6 +86,15 @@ /* Chars needed to store LONGLONG, excluding trailing '\0'. */ #define LONGLONG_LEN 20 +/* general_log or slow_log tables under mysql database */ +static inline my_bool general_log_or_slow_log_tables(const char *db, + const char *table) +{ + return (strcmp(db, "mysql") == 0) && + ((strcmp(table, "general_log") == 0) || + (strcmp(table, "slow_log") == 0)); +} + static void add_load_option(DYNAMIC_STRING *str, const char *option, const char *option_value); static ulong find_set(TYPELIB *lib, const char *x, uint length, @@ -106,6 +116,8 @@ 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_slave_apply= 0, + opt_include_master_host_port= 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; @@ -126,7 +138,10 @@ static my_bool server_supports_switching_charsets= TRUE; static ulong opt_compatible_mode= 0; #define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1 #define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2 +#define MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL 1 +#define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2 static uint opt_mysql_port= 0, opt_master_data; +static uint opt_slave_data; static uint my_end_arg; static char * opt_mysql_unix_port=0; static int first_error=0; @@ -139,6 +154,7 @@ FILE *stderror_file=0; static char *shared_memory_base_name=0; #endif static uint opt_protocol= 0; +static char *opt_plugin_dir= 0, *opt_default_auth= 0; /* Dynamic_string wrapper functions. In this file use these @@ -187,9 +203,6 @@ HASH ignore_table; static struct my_option my_long_options[] = { - {"all", OPT_ALL, "Deprecated. Use --create-options instead.", - &create_options, &create_options, 0, GET_BOOL, NO_ARG, 1, - 0, 0, 0, 0, 0}, {"all-databases", 'A', "Dump all the databases. This will be same as --databases with all databases selected.", &opt_alldbs, &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, @@ -214,10 +227,10 @@ static struct my_option my_long_options[] = {"allow-keywords", OPT_KEYWORDS, "Allow creation of column names that are keywords.", &opt_keywords, &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef __NETWARE__ - {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, -#endif + {"apply-slave-statements", OPT_MYSQLDUMP_SLAVE_APPLY, + "Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.", + &opt_slave_apply, &opt_slave_apply, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, "Directory for character set files.", (char**) &charsets_dir, (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -225,13 +238,20 @@ static struct my_option my_long_options[] = &opt_comments, &opt_comments, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"compatible", OPT_COMPATIBLE, - "Change the dump to be compatible with a given mode. By default tables are dumped in a format optimized for MySQL. Legal modes are: ansi, mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option is ignored with earlier server versions.", + "Change the dump to be compatible with a given mode. By default tables " + "are dumped in a format optimized for MySQL. Legal modes are: ansi, " + "mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, " + "no_table_options, no_field_options. One can use several modes separated " + "by commas. Note: Requires MySQL server version 4.1.0 or higher. " + "This option is ignored with earlier server versions.", &opt_compatible_mode_str, &opt_compatible_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compact", OPT_COMPACT, - "Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs. Enables options --skip-add-drop-table --skip-add-locks --skip-comments --skip-disable-keys --skip-set-charset.", - &opt_compact, &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, - 0, 0}, + "Give less verbose output (useful for debugging). Disables structure " + "comments and header/footer constructs. Enables options --skip-add-" + "drop-table --skip-add-locks --skip-comments --skip-disable-keys " + "--skip-set-charset.", + &opt_compact, &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"complete-insert", 'c', "Use complete insert statements.", &opt_complete_insert, &opt_complete_insert, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -270,8 +290,22 @@ static struct my_option my_long_options[] = &opt_delete_master_logs, &opt_delete_master_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"disable-keys", 'K', - "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", &opt_disable_keys, + "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER " + "TABLE tb_name ENABLE KEYS */; will be put in the output.", &opt_disable_keys, &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"dump-slave", OPT_MYSQLDUMP_SLAVE_DATA, + "This causes the binary log position and filename of the master to be " + "appended to the dumped data output. Setting the value to 1, will print" + "it as a CHANGE MASTER command in the dumped data output; if equal" + " to 2, that command will be prefixed with a comment symbol. " + "This option will turn --lock-all-tables on, unless " + "--single-transaction is specified too (in which case a " + "global read lock is only taken a short time at the beginning of the dump " + "- don't forget to read about --single-transaction below). In all cases " + "any action on logs will happen at the exact moment of the dump." + "Option automatically turns --lock-tables off.", + &opt_slave_data, &opt_slave_data, 0, + GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0}, {"events", 'E', "Dump events.", &opt_events, &opt_events, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -280,24 +314,18 @@ static struct my_option my_long_options[] = &extended_insert, &extended_insert, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"fields-terminated-by", OPT_FTB, - "Fields in the output file are terminated by the given string.", - &fields_terminated, &fields_terminated, 0, + "Fields in the output file are terminated by the given string.", + &fields_terminated, &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"fields-enclosed-by", OPT_ENC, - "Fields in the output file are enclosed by the given character.", - &enclosed, &enclosed, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, + "Fields in the output file are enclosed by the given character.", + &enclosed, &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, {"fields-optionally-enclosed-by", OPT_O_ENC, - "Fields in the output file are optionally enclosed by the given character.", - &opt_enclosed, &opt_enclosed, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, - {"fields-escaped-by", OPT_ESC, + "Fields in the output file are optionally enclosed by the given character.", + &opt_enclosed, &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, + {"fields-escaped-by", OPT_ESC, "Fields in the output file are escaped by the given character.", - &escaped, &escaped, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"first-slave", OPT_FIRST_SLAVE, "Deprecated, renamed to --lock-all-tables.", - &opt_lock_all_tables, &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, - 0, 0, 0, 0, 0, 0}, + &escaped, &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"flush-logs", 'F', "Flush logs file in server before starting dump. " "Note that if you dump many databases at once (using the option " "--databases= or --all-databases), the logs will be flushed for " @@ -331,10 +359,15 @@ static struct my_option my_long_options[] = "be specified with both database and table names, e.g., " "--ignore-table=database.table.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"include-master-host-port", OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT, + "Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' " + "in dump produced with --dump-slave.", &opt_include_master_host_port, + &opt_include_master_host_port, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.", &opt_ignore, &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"lines-terminated-by", OPT_LTB, + {"lines-terminated-by", OPT_LTB, "Lines in the output file are terminated by the given string.", &lines_terminated, &lines_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -385,7 +418,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-data", 'd', "No row information.", &opt_no_data, &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"no-set-names", 'N',"Suppress the SET NAMES statement", + {"no-set-names", 'N', "Same as --skip-set-charset.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"opt", OPT_OPTIMIZE, "Same as --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys. Enabled by default, disable with --skip-opt.", @@ -415,18 +448,17 @@ static struct my_option my_long_options[] = &opt_replace_into, &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"result-file", 'r', - "Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Direct output to a given file. This option should be used in systems " + "(e.g., DOS, Windows) that use carriage-return linefeed pairs (\\r\\n) " + "to separate text lines. This option ensures that only a single newline " + "is used.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"routines", 'R', "Dump stored routines (functions and procedures).", - &opt_routines, &opt_routines, 0, GET_BOOL, - NO_ARG, 0, 0, 0, 0, 0, 0}, + &opt_routines, &opt_routines, 0, GET_BOOL, + NO_ARG, 0, 0, 0, 0, 0, 0}, {"set-charset", OPT_SET_CHARSET, - "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.", + "Add 'SET NAMES default_character_set' to the output.", &opt_set_charset, &opt_set_charset, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"set-variable", 'O', - "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, @@ -485,6 +517,13 @@ static struct my_option my_long_options[] = &where, &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.", + &opt_plugin_dir, &opt_plugin_dir, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"default_auth", OPT_DEFAULT_AUTH, + "Default authentication client-side plugin to use.", + &opt_default_auth, &opt_default_auth, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -517,7 +556,6 @@ static int dump_tablespaces(char* ts_where); static void print_comment(FILE *sql_file, my_bool is_error, const char *format, ...); -#include <help_start.h> /* Print the supplied message if in verbose mode @@ -540,6 +578,8 @@ static void verbose_msg(const char *fmt, ...) vfprintf(stderr, fmt, args); va_end(args); + fflush(stderr); + DBUG_VOID_RETURN; } @@ -559,19 +599,17 @@ void check_io(FILE *file) static void print_version(void) { - printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION, + printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname_short,DUMP_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); - NETWARE_SET_SCREEN_MODE(1); } /* print_version */ static void short_usage_sub(void) { - printf("Usage: %s [OPTIONS] database [tables]\n", my_progname); + printf("Usage: %s [OPTIONS] database [tables]\n", my_progname_short); printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n", - my_progname); - printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname); - NETWARE_SET_SCREEN_MODE(1); + my_progname_short); + printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname_short); } @@ -591,11 +629,9 @@ static void usage(void) static void short_usage(void) { short_usage_sub(); - printf("For more options, use %s --help\n", my_progname); + printf("For more options, use %s --help\n", my_progname_short); } -#include <help_end.h> - static void write_header(FILE *sql_file, char *db_name) { @@ -708,12 +744,6 @@ static void write_footer(FILE *sql_file) } /* write_footer */ -static void free_table_ent(char *key) -{ - my_free(key, MYF(0)); -} - - uchar* get_table_key(const char *entry, size_t *length, my_bool not_used __attribute__((unused))) { @@ -727,18 +757,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { switch (optid) { -#ifdef __NETWARE__ - case OPT_AUTO_CLOSE: - setscreenmode(SCR_AUTOCLOSE_ON_EXIT); - break; -#endif case 'p': if (argument == disabled_my_option) argument= (char*) ""; /* Don't require password */ if (argument) { char *start=argument; - my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); + my_free(opt_password); opt_password=my_strdup(argument,MYF(MY_FAE)); while (*argument) *argument++= 'x'; /* Destroy argument */ if (*start) @@ -794,19 +819,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case '?': usage(); exit(0); - case 'O': - WARN_DEPRECATED(VER_CELOSIA, "--set-variable", "--variable-name=value"); - break; - case (int) OPT_ALL: - WARN_DEPRECATED(VER_CELOSIA, "--all", "--create-options"); - break; - case (int) OPT_FIRST_SLAVE: - WARN_DEPRECATED(VER_CELOSIA, "--first-slave", "--lock-all-tables"); - break; case (int) OPT_MASTER_DATA: if (!argument) /* work like in old versions */ opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL; break; + case (int) OPT_MYSQLDUMP_SLAVE_DATA: + if (!argument) /* work like in old versions */ + opt_slave_data= MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL; + break; case (int) OPT_OPTIMIZE: extended_insert= opt_drop= opt_lock= quick= create_options= opt_disable_keys= lock_tables= opt_set_charset= 1; @@ -902,12 +922,12 @@ static int get_options(int *argc, char ***argv) opt_net_buffer_length= *mysql_params->p_net_buffer_length; md_result_file= stdout; - load_defaults("my",load_default_groups,argc,argv); + if (load_defaults("my",load_default_groups,argc,argv)) + return 1; defaults_argv= *argv; - if (hash_init(&ignore_table, charset_info, 16, 0, 0, - (hash_get_key) get_table_key, - (hash_free_key) free_table_ent, 0)) + if (my_hash_init(&ignore_table, charset_info, 16, 0, 0, + (my_hash_get_key) get_table_key, my_free, 0)) return(EX_EOM); /* Don't copy internal log tables */ if (my_hash_insert(&ignore_table, @@ -936,33 +956,44 @@ static int get_options(int *argc, char ***argv) fields_terminated)) { fprintf(stderr, - "%s: You must use option --tab with --fields-...\n", my_progname); + "%s: You must use option --tab with --fields-...\n", my_progname_short); return(EX_USAGE); } + /* We don't delete master logs if slave data option */ + if (opt_slave_data) + { + opt_lock_all_tables= !opt_single_transaction; + opt_master_data= 0; + opt_delete_master_logs= 0; + } + /* Ensure consistency of the set of binlog & locking options */ if (opt_delete_master_logs && !opt_master_data) opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL; if (opt_single_transaction && opt_lock_all_tables) { fprintf(stderr, "%s: You can't use --single-transaction and " - "--lock-all-tables at the same time.\n", my_progname); + "--lock-all-tables at the same time.\n", my_progname_short); return(EX_USAGE); } if (opt_master_data) + { opt_lock_all_tables= !opt_single_transaction; + opt_slave_data= 0; + } if (opt_single_transaction || opt_lock_all_tables) lock_tables= 0; if (enclosed && opt_enclosed) { - fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname); + fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname_short); return(EX_USAGE); } if ((opt_databases || opt_alldbs) && path) { fprintf(stderr, "%s: --databases or --all-databases can't be used with --tab.\n", - my_progname); + my_progname_short); return(EX_USAGE); } if (strcmp(default_charset, charset_info->csname) && @@ -1014,7 +1045,7 @@ static void die(int error_num, const char* fmt_reason, ...) my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args); va_end(args); - fprintf(stderr, "%s: %s\n", my_progname, buffer); + fprintf(stderr, "%s: %s\n", my_progname_short, buffer); fflush(stderr); ignore_errors= 0; /* force the exit */ @@ -1048,7 +1079,7 @@ static void maybe_die(int error_num, const char* fmt_reason, ...) my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args); va_end(args); - fprintf(stderr, "%s: %s\n", my_progname, buffer); + fprintf(stderr, "%s: %s\n", my_progname_short, buffer); fflush(stderr); maybe_exit(error_num); @@ -1361,120 +1392,68 @@ static int switch_character_set_results(MYSQL *mysql, const char *cs_name) } /** - Rewrite CREATE TRIGGER statement, enclosing DEFINER clause in - version-specific comment. - - This function parses the CREATE TRIGGER statement and encloses - DEFINER-clause in version-specific comment: - input query: CREATE DEFINER=a@b TRIGGER ... - rewritten query: CREATE * / / *!50017 DEFINER=a@b * / / *!50003 TRIGGER ... - - @note This function will go away when WL#3995 is implemented. - - @param[in] trigger_def_str CREATE TRIGGER statement string. - @param[in] trigger_def_length length of the trigger_def_str. - - @return pointer to the new allocated query string. -*/ - -static char *cover_definer_clause_in_trigger(const char *trigger_def_str, - uint trigger_def_length) -{ - char *query_str= NULL; - char *definer_begin= my_case_str(trigger_def_str, trigger_def_length, - C_STRING_WITH_LEN(" DEFINER")); - char *definer_end; - - if (!definer_begin) - return NULL; - - definer_end= my_case_str(definer_begin, strlen(definer_begin), - C_STRING_WITH_LEN(" TRIGGER")); - - if (definer_end) - { - char *query_str_tail; - - /* - Allocate memory for new query string: original string - from SHOW statement and version-specific comments. - */ - query_str= alloc_query_str(trigger_def_length + 23); - - query_str_tail= strnmov(query_str, - trigger_def_str, - definer_begin - trigger_def_str); - - query_str_tail= strmov(query_str_tail, - "*/ /*!50017"); - - query_str_tail= strnmov(query_str_tail, - definer_begin, - definer_end - definer_begin); - - query_str_tail= strxmov(query_str_tail, - "*/ /*!50003", - definer_end, - NullS); - } - - return query_str; -} - -/** - Rewrite CREATE FUNCTION or CREATE PROCEDURE statement, enclosing DEFINER - clause in version-specific comment. + Rewrite statement, enclosing DEFINER clause in version-specific comment. - This function parses the CREATE FUNCTION | PROCEDURE statement and - encloses DEFINER-clause in version-specific comment: + This function parses any CREATE statement and encloses DEFINER-clause in + version-specific comment: input query: CREATE DEFINER=a@b FUNCTION ... rewritten query: CREATE * / / *!50020 DEFINER=a@b * / / *!50003 FUNCTION ... @note This function will go away when WL#3995 is implemented. - @param[in] def_str CREATE FUNCTION|PROCEDURE statement string. - @param[in] def_str_length length of the def_str. + @param[in] stmt_str CREATE statement string. + @param[in] stmt_length Length of the stmt_str. + @param[in] definer_version_str Minimal MySQL version number when + DEFINER clause is supported in the + given statement. + @param[in] definer_version_length Length of definer_version_str. + @param[in] stmt_version_str Minimal MySQL version number when the + given statement is supported. + @param[in] stmt_version_length Length of stmt_version_str. + @param[in] keyword_str Keyword to look for after CREATE. + @param[in] keyword_length Length of keyword_str. @return pointer to the new allocated query string. */ -static char *cover_definer_clause_in_sp(const char *def_str, - uint def_str_length) +static char *cover_definer_clause(const char *stmt_str, + uint stmt_length, + const char *definer_version_str, + uint definer_version_length, + const char *stmt_version_str, + uint stmt_version_length, + const char *keyword_str, + uint keyword_length) { - char *query_str= NULL; - char *definer_begin= my_case_str(def_str, def_str_length, + char *definer_begin= my_case_str(stmt_str, stmt_length, C_STRING_WITH_LEN(" DEFINER")); - char *definer_end; + char *definer_end= NULL; + + char *query_str= NULL; + char *query_ptr; if (!definer_begin) return NULL; definer_end= my_case_str(definer_begin, strlen(definer_begin), - C_STRING_WITH_LEN(" PROCEDURE")); + keyword_str, keyword_length); if (!definer_end) - { - definer_end= my_case_str(definer_begin, strlen(definer_begin), - C_STRING_WITH_LEN(" FUNCTION")); - } + return NULL; - if (definer_end) - { - char *query_str_tail; + /* + Allocate memory for new query string: original string + from SHOW statement and version-specific comments. + */ + query_str= alloc_query_str(stmt_length + 23); - /* - Allocate memory for new query string: original string - from SHOW statement and version-specific comments. - */ - query_str= alloc_query_str(def_str_length + 23); - - query_str_tail= strnmov(query_str, def_str, definer_begin - def_str); - query_str_tail= strmov(query_str_tail, "*/ /*!50020"); - query_str_tail= strnmov(query_str_tail, definer_begin, - definer_end - definer_begin); - query_str_tail= strxmov(query_str_tail, "*/ /*!50003", - definer_end, NullS); - } + query_ptr= strnmov(query_str, stmt_str, definer_begin - stmt_str); + query_ptr= strnmov(query_ptr, C_STRING_WITH_LEN("*/ /*!")); + query_ptr= strnmov(query_ptr, definer_version_str, definer_version_length); + query_ptr= strnmov(query_ptr, definer_begin, definer_end - definer_begin); + query_ptr= strnmov(query_ptr, C_STRING_WITH_LEN("*/ /*!")); + query_ptr= strnmov(query_ptr, stmt_version_str, stmt_version_length); + query_ptr= strxmov(query_ptr, definer_end, NullS); return query_str; } @@ -1506,16 +1485,17 @@ static void free_resources() { if (md_result_file && md_result_file != stdout) my_fclose(md_result_file, MYF(0)); - my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); - my_free(current_host, MYF(MY_ALLOW_ZERO_PTR)); - if (hash_inited(&ignore_table)) - hash_free(&ignore_table); + my_free(opt_password); + my_free(current_host); + if (my_hash_inited(&ignore_table)) + my_hash_free(&ignore_table); if (extended_insert) dynstr_free(&extended_row); if (insert_pat_inited) dynstr_free(&insert_pat); if (defaults_argv) free_defaults(defaults_argv); + mysql_library_end(); my_end(my_end_arg); } @@ -1560,9 +1540,16 @@ static int connect_to_db(char *host, char *user,char *passwd) mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); #endif mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); - if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd, - NULL,opt_mysql_port,opt_mysql_unix_port, - 0))) + + if (opt_plugin_dir && *opt_plugin_dir) + mysql_options(&mysql_connection, MYSQL_PLUGIN_DIR, opt_plugin_dir); + + if (opt_default_auth && *opt_default_auth) + mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth); + + mysql= &mysql_connection; /* So we can mysql_close() it properly */ + if (!mysql_real_connect(&mysql_connection,host,user,passwd, + NULL,opt_mysql_port,opt_mysql_unix_port, 0)) { DB_error(&mysql_connection, "when trying to connect"); DBUG_RETURN(1); @@ -1621,7 +1608,7 @@ static void unescape(FILE *file,char *pos,uint length) fputs(tmp, file); fputc('\'', file); check_io(file); - my_free(tmp, MYF(MY_WME)); + my_free(tmp); DBUG_VOID_RETURN; } /* unescape */ @@ -2165,6 +2152,8 @@ static uint dump_events_for_db(char *db) */ if (strlen(row[3]) != 0) { + char *query_str; + if (opt_drop) fprintf(sql_file, "/*!50106 DROP EVENT IF EXISTS %s */%s\n", event_name, delimiter); @@ -2172,7 +2161,7 @@ static uint dump_events_for_db(char *db) if (create_delimiter(row[3], delimiter, sizeof(delimiter)) == NULL) { fprintf(stderr, "%s: Warning: Can't create delimiter for event '%s'\n", - my_progname, event_name); + my_progname_short, event_name); DBUG_RETURN(1); } @@ -2191,31 +2180,36 @@ static uint dump_events_for_db(char *db) row[4], /* character_set_results */ row[5]); /* collation_connection */ } - else - { - /* - mysqldump is being run against the server, that does not - provide character set information in SHOW CREATE - statements. + else + { + /* + mysqldump is being run against the server, that does not + provide character set information in SHOW CREATE + statements. - NOTE: the dump may be incorrect, since character set - information is required in order to restore event properly. - */ + NOTE: the dump may be incorrect, since character set + information is required in order to restore event properly. + */ - fprintf(sql_file, - "--\n" - "-- WARNING: old server version. " - "The following dump may be incomplete.\n" - "--\n"); - } + fprintf(sql_file, + "--\n" + "-- WARNING: old server version. " + "The following dump may be incomplete.\n" + "--\n"); + } switch_sql_mode(sql_file, delimiter, row[1]); switch_time_zone(sql_file, delimiter, row[2]); + query_str= cover_definer_clause(row[3], strlen(row[3]), + C_STRING_WITH_LEN("50117"), + C_STRING_WITH_LEN("50106"), + C_STRING_WITH_LEN(" EVENT")); + fprintf(sql_file, "/*!50106 %s */ %s\n", - (const char *) row[3], + (const char *) (query_str != NULL ? query_str : row[3]), (const char *) delimiter); restore_time_zone(sql_file, delimiter); @@ -2254,7 +2248,7 @@ static uint dump_events_for_db(char *db) mysql_free_result(event_list_res); if (lock_tables) - VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); + (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"); DBUG_RETURN(0); } @@ -2394,7 +2388,16 @@ static uint dump_routines_for_db(char *db) fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n", routine_type[i], routine_name); - query_str= cover_definer_clause_in_sp(row[2], strlen(row[2])); + query_str= cover_definer_clause(row[2], strlen(row[2]), + C_STRING_WITH_LEN("50020"), + C_STRING_WITH_LEN("50003"), + C_STRING_WITH_LEN(" FUNCTION")); + + if (!query_str) + query_str= cover_definer_clause(row[2], strlen(row[2]), + C_STRING_WITH_LEN("50020"), + C_STRING_WITH_LEN("50003"), + C_STRING_WITH_LEN(" PROCEDURE")); if (mysql_num_fields(routine_res) >= 6) { @@ -2450,7 +2453,7 @@ static uint dump_routines_for_db(char *db) } } - my_free(query_str, MYF(MY_ALLOW_ZERO_PTR)); + my_free(query_str); } } /* end of routine printing */ mysql_free_result(routine_res); @@ -2470,7 +2473,7 @@ static uint dump_routines_for_db(char *db) DBUG_RETURN(1); if (lock_tables) - VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); + (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"); DBUG_RETURN(0); } @@ -2509,6 +2512,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, "TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'"; FILE *sql_file= md_result_file; int len; + my_bool is_log_table; MYSQL_RES *result; MYSQL_ROW row; DBUG_ENTER("get_table_structure"); @@ -2593,9 +2597,12 @@ static uint get_table_structure(char *table, char *db, char *table_type, /* Even if the "table" is a view, we do a DROP TABLE here. The view-specific code below fills in the DROP VIEW. + We will skip the DROP TABLE for general_log and slow_log, since + those stmts will fail, in case we apply dump by enabling logging. */ - fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", - opt_quoted_table); + if (!general_log_or_slow_log_tables(db, table)) + fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", + opt_quoted_table); check_io(sql_file); } @@ -2603,6 +2610,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, if (strcmp(field->name, "View") == 0) { char *scv_buff= NULL; + my_ulonglong n_cols; verbose_msg("-- It's a view, create dummy table for view\n"); @@ -2617,8 +2625,8 @@ static uint get_table_structure(char *table, char *db, char *table_type, the same name in order to satisfy views that depend on this view. The table will be removed when the actual view is created. - The properties of each column, aside from the data type, are not - preserved in this temporary table, because they are not necessary. + The properties of each column, are not preserved in this temporary + table, because they are not necessary. This will not be necessary once we can determine dependencies between views and can simply dump them in the appropriate order. @@ -2638,15 +2646,30 @@ static uint get_table_structure(char *table, char *db, char *table_type, if (mysql_errno(mysql) == ER_VIEW_INVALID) fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : ""); - my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); + my_free(scv_buff); DBUG_RETURN(0); } else - my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); + my_free(scv_buff); - if (mysql_num_rows(result)) + n_cols= mysql_num_rows(result); + if (0 != n_cols) { + + /* + The actual formula is based on the column names and how the .FRM + files are stored and is too volatile to be repeated here. + Thus we simply warn the user if the columns exceed a limit we + know works most of the time. + */ + if (n_cols >= 1000) + fprintf(stderr, + "-- Warning: Creating a stand-in table for view %s may" + " fail when replaying the dump file produced because " + "of the number of columns exceeding 1000. Exercise " + "caution when replaying the produced dump file.\n", + table); if (opt_drop) { /* @@ -2673,14 +2696,19 @@ static uint get_table_structure(char *table, char *db, char *table_type, row= mysql_fetch_row(result); - fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0), - row[1]); + /* + The actual column type doesn't matter anyway, since the table will + be dropped at run time. + We do tinyint to avoid hitting the row size limit. + */ + fprintf(sql_file, " %s tinyint NOT NULL", + quote_name(row[0], name_buff, 0)); while((row= mysql_fetch_row(result))) { /* col name, col type */ - fprintf(sql_file, ",\n %s %s", - quote_name(row[0], name_buff, 0), row[1]); + fprintf(sql_file, ",\n %s tinyint NOT NULL", + quote_name(row[0], name_buff, 0)); } /* @@ -2707,12 +2735,25 @@ static uint get_table_structure(char *table, char *db, char *table_type, row= mysql_fetch_row(result); - fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" : - "/*!40101 SET @saved_cs_client = @@character_set_client */;\n" - "/*!40101 SET character_set_client = utf8 */;\n" - "%s;\n" - "/*!40101 SET character_set_client = @saved_cs_client */;\n", - row[1]); + is_log_table= general_log_or_slow_log_tables(db, table); + if (is_log_table) + row[1]+= 13; /* strlen("CREATE TABLE ")= 13 */ + if (opt_compatible_mode & 3) + { + fprintf(sql_file, + is_log_table ? "CREATE TABLE IF NOT EXISTS %s;\n" : "%s;\n", + row[1]); + } + else + { + fprintf(sql_file, + "/*!40101 SET @saved_cs_client = @@character_set_client */;\n" + "/*!40101 SET character_set_client = utf8 */;\n" + "%s%s;\n" + "/*!40101 SET character_set_client = @saved_cs_client */;\n", + is_log_table ? "CREATE TABLE IF NOT EXISTS " : "", + row[1]); + } check_io(sql_file); mysql_free_result(result); @@ -2772,7 +2813,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, else { verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n", - my_progname, mysql_error(mysql)); + my_progname_short, mysql_error(mysql)); my_snprintf(query_buff, sizeof(query_buff), show_fields_stmt, db, table); @@ -2883,7 +2924,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, goto continue_xml; } fprintf(stderr, "%s: Can't get keys for table %s (%s)\n", - my_progname, result_table, mysql_error(mysql)); + my_progname_short, result_table, mysql_error(mysql)); if (path) my_fclose(sql_file, MYF(MY_WME)); DBUG_RETURN(0); @@ -3108,9 +3149,10 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs, continue; } - query_str= cover_definer_clause_in_trigger(row[2], strlen(row[2])); - - + query_str= cover_definer_clause(row[2], strlen(row[2]), + C_STRING_WITH_LEN("50017"), + C_STRING_WITH_LEN("50003"), + C_STRING_WITH_LEN(" TRIGGER")); if (switch_db_collation(sql_file, db_name, ";", db_cl_name, row[5], &db_cl_altered)) DBUG_RETURN(TRUE); @@ -3137,7 +3179,7 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs, DBUG_RETURN(TRUE); } - my_free(query_str, MYF(MY_ALLOW_ZERO_PTR)); + my_free(query_str); } DBUG_RETURN(FALSE); @@ -3538,7 +3580,7 @@ static void dump_table(char *table, char *db) if (mysql_num_fields(res) != num_fields) { fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n", - my_progname, result_table); + my_progname_short, result_table); error= EX_CONSCHECK; goto err; } @@ -3622,7 +3664,7 @@ static void dump_table(char *table, char *db) { if (length) { - if (!IS_NUM_FIELD(field)) + if (!(field->flags & NUM_FLAG)) { /* "length * 2 + 2" is OK for both HEX and non-HEX modes: @@ -3690,7 +3732,7 @@ static void dump_table(char *table, char *db) } if (row[i]) { - if (!IS_NUM_FIELD(field)) + if (!(field->flags & NUM_FLAG)) { if (opt_xml) { @@ -3803,7 +3845,7 @@ static void dump_table(char *table, char *db) { my_snprintf(buf, sizeof(buf), "%s: Error %d: %s when dumping table %s at row: %ld\n", - my_progname, + my_progname_short, mysql_errno(mysql), mysql_error(mysql), result_table, @@ -3997,8 +4039,8 @@ static int dump_tablespaces(char* ts_where) DBUG_RETURN(0); } - my_printf_error(0, "Error: '%s' when trying to dump tablespaces", - MYF(0), mysql_error(mysql)); + fprintf(stderr, "%s: Error: '%s' when trying to dump tablespaces\n", + my_progname_short, mysql_error(mysql)); DBUG_RETURN(1); } @@ -4127,8 +4169,12 @@ static int dump_all_databases() return 1; while ((row= mysql_fetch_row(tableres))) { - if (mysql_get_server_version(mysql) >= 50003 && - !my_strcasecmp(&my_charset_latin1, row[0], "information_schema")) + if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, row[0], INFORMATION_SCHEMA_DB_NAME)) + continue; + + if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, row[0], PERFORMANCE_SCHEMA_DB_NAME)) continue; if (dump_all_tables_in_db(row[0])) @@ -4139,14 +4185,18 @@ static int dump_all_databases() if (mysql_query(mysql, "SHOW DATABASES") || !(tableres= mysql_store_result(mysql))) { - my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", - MYF(0), mysql_error(mysql)); + fprintf(stderr, "%s: Error: Couldn't execute 'SHOW DATABASES': %s\n", + my_progname_short, mysql_error(mysql)); return 1; } while ((row= mysql_fetch_row(tableres))) { - if (mysql_get_server_version(mysql) >= 50003 && - !my_strcasecmp(&my_charset_latin1, row[0], "information_schema")) + if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, row[0], INFORMATION_SCHEMA_DB_NAME)) + continue; + + if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, row[0], PERFORMANCE_SCHEMA_DB_NAME)) continue; if (dump_all_views_in_db(row[0])) @@ -4290,7 +4340,7 @@ static int init_dumping(char *database, int init_func(char*)) my_bool include_table(const uchar *hash_key, size_t len) { - return !hash_search(&ignore_table, hash_key, len); + return ! my_hash_search(&ignore_table, hash_key, len); } @@ -4312,6 +4362,22 @@ static int dump_all_tables_in_db(char *database) if (opt_xml) print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS); + if (strcmp(database, "mysql") == 0) + { + char table_type[NAME_LEN]; + char ignore_flag; + uint num_fields; + num_fields= get_table_structure((char *) "general_log", + database, table_type, &ignore_flag); + if (num_fields == 0) + verbose_msg("-- Warning: get_table_structure() failed with some internal " + "error for 'general_log' table\n"); + num_fields= get_table_structure((char *) "slow_log", + database, table_type, &ignore_flag); + if (num_fields == 0) + verbose_msg("-- Warning: get_table_structure() failed with some internal " + "error for 'slow_log' table\n"); + } if (lock_tables) { DYNAMIC_STRING query; @@ -4336,6 +4402,8 @@ static int dump_all_tables_in_db(char *database) if (mysql_refresh(mysql, REFRESH_LOG)) DB_error(mysql, "when doing refresh"); /* We shall continue here, if --force was given */ + else + verbose_msg("-- dump_all_tables_in_db : logs flushed successfully!\n"); } while ((table= getTableName(0))) { @@ -4343,7 +4411,7 @@ static int dump_all_tables_in_db(char *database) if (include_table((uchar*) hash_key, end - hash_key)) { dump_table(table,database); - my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); + my_free(order_by); order_by= 0; if (opt_dump_triggers && mysql_get_server_version(mysql) >= 50009) { @@ -4372,7 +4440,7 @@ static int dump_all_tables_in_db(char *database) check_io(md_result_file); } if (lock_tables) - VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); + (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"); if (flush_privileges && using_mysql_db == 0) { fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n"); @@ -4433,6 +4501,8 @@ static my_bool dump_all_views_in_db(char *database) if (mysql_refresh(mysql, REFRESH_LOG)) DB_error(mysql, "when doing refresh"); /* We shall continue here, if --force was given */ + else + verbose_msg("-- dump_all_views_in_db : logs flushed successfully!\n"); } while ((table= getTableName(0))) { @@ -4446,7 +4516,7 @@ static my_bool dump_all_views_in_db(char *database) check_io(md_result_file); } if (lock_tables) - VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); + (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"); return 0; } /* dump_all_tables_in_db */ @@ -4495,7 +4565,7 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root) } mysql_free_result(table_res); } - DBUG_PRINT("exit", ("new_table_name: %s", val_or_null(name))); + DBUG_PRINT("exit", ("new_table_name: %s", name)); DBUG_RETURN(name); } @@ -4542,10 +4612,12 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } end= pos; - /* Can't LOCK TABLES in INFORMATION_SCHEMA, so don't try. */ + /* Can't LOCK TABLES in I_S / P_S, so don't try. */ if (lock_tables && - !(mysql_get_server_version(mysql) >= 50003 && - !my_strcasecmp(&my_charset_latin1, db, "information_schema"))) + !(mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, db, INFORMATION_SCHEMA_DB_NAME)) && + !(mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, db, PERFORMANCE_SCHEMA_DB_NAME))) { if (mysql_real_query(mysql, lock_tables_query.str, lock_tables_query.length-1)) @@ -4569,6 +4641,8 @@ static int dump_selected_tables(char *db, char **table_names, int tables) DB_error(mysql, "when doing refresh"); } /* We shall countinue here, if --force was given */ + else + verbose_msg("-- dump_selected_tables : logs flushed successfully!\n"); } if (opt_xml) print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NullS); @@ -4608,7 +4682,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) dump_routines_for_db(db); } free_root(&root, MYF(0)); - my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); + my_free(order_by); order_by= 0; if (opt_xml) { @@ -4616,7 +4690,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) check_io(md_result_file); } if (lock_tables) - VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); + (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"); DBUG_RETURN(0); } /* dump_selected_tables */ @@ -4624,7 +4698,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) { MYSQL_ROW row; - MYSQL_RES *master; + MYSQL_RES *UNINIT_VAR(master); char binlog_pos_file[FN_REFLEN]; char binlog_pos_offset[LONGLONG_LEN+1]; char *file, *offset; @@ -4655,8 +4729,8 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) if (!ignore_errors) { /* SHOW MASTER STATUS reports nothing and --force is not enabled */ - my_printf_error(0, "Error: Binlogging on server not active", - MYF(0)); + fprintf(stderr, "%s: Error: Binlogging on server not active\n", + my_progname_short); maybe_exit(EX_MYSQLERR); return 1; } @@ -4668,10 +4742,9 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) } /* SHOW MASTER STATUS reports file and position */ - if (opt_comments) - print_comment(md_result_file, 0, - "\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, file, offset); @@ -4683,6 +4756,130 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) return 0; } +static int do_stop_slave_sql(MYSQL *mysql_con) +{ + MYSQL_RES *slave; + /* We need to check if the slave sql is running in the first place */ + if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS")) + return(1); + else + { + MYSQL_ROW row= mysql_fetch_row(slave); + if (row && row[11]) + { + /* if SLAVE SQL is not running, we don't stop it */ + if (!strcmp(row[11],"No")) + { + mysql_free_result(slave); + /* Silently assume that they don't have the slave running */ + return(0); + } + } + } + mysql_free_result(slave); + + /* now, stop slave if running */ + if (mysql_query_with_error_report(mysql_con, 0, "STOP SLAVE SQL_THREAD")) + return(1); + + return(0); +} + +static int add_stop_slave(void) +{ + if (opt_comments) + fprintf(md_result_file, + "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n"); + fprintf(md_result_file, "STOP SLAVE;\n"); + return(0); +} + +static int add_slave_statements(void) +{ + if (opt_comments) + fprintf(md_result_file, + "\n--\n-- start slave statement to make a recovery dump)\n--\n\n"); + fprintf(md_result_file, "START SLAVE;\n"); + return(0); +} + +static int do_show_slave_status(MYSQL *mysql_con) +{ + MYSQL_RES *slave= 0; + const char *comment_prefix= + (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : ""; + if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS")) + { + if (!ignore_errors) + { + /* SHOW SLAVE STATUS reports nothing and --force is not enabled */ + fprintf(stderr, "%s: Error: Slave not set up\n", my_progname_short); + } + mysql_free_result(slave); + return 1; + } + else + { + MYSQL_ROW row= mysql_fetch_row(slave); + if (row && row[9] && row[21]) + { + /* 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 (the master of this slave)\n--\n\n"); + + fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix); + + if (opt_include_master_host_port) + { + if (row[1]) + fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]); + if (row[3]) + fprintf(md_result_file, "MASTER_PORT=%s, ", row[3]); + } + fprintf(md_result_file, + "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]); + + check_io(md_result_file); + } + mysql_free_result(slave); + } + return 0; +} + +static int do_start_slave_sql(MYSQL *mysql_con) +{ + MYSQL_RES *slave; + /* We need to check if the slave sql is stopped in the first place */ + if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS")) + return(1); + else + { + MYSQL_ROW row= mysql_fetch_row(slave); + if (row && row[11]) + { + /* if SLAVE SQL is not running, we don't start it */ + if (!strcmp(row[11],"Yes")) + { + mysql_free_result(slave); + /* Silently assume that they don't have the slave running */ + return(0); + } + } + } + mysql_free_result(slave); + + /* now, start slave if stopped */ + if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE")) + { + fprintf(stderr, "%s: Error: Unable to start slave\n", my_progname_short); + return 1; + } + return(0); +} + + static int do_flush_tables_read_lock(MYSQL *mysql_con) { @@ -4749,6 +4946,7 @@ static int purge_bin_logs_to(MYSQL *mysql_con, char* log_name) static int start_transaction(MYSQL *mysql_con) { + verbose_msg("-- Starting transaction...\n"); /* We use BEGIN for old servers. --single-transaction --master-data will fail on old servers, but that's ok as it was already silently broken (it didn't @@ -4803,7 +5001,7 @@ static ulong find_set(TYPELIB *lib, const char *x, uint length, for (; pos != end && *pos != ','; pos++) ; var_len= (uint) (pos - start); strmake(buff, start, min(sizeof(buff) - 1, var_len)); - find= find_type(buff, lib, var_len); + find= find_type(buff, lib, FIND_TYPE_BASIC); if (!find) { *err_pos= (char*) start; @@ -5317,8 +5515,9 @@ int main(int argc, char **argv) char bin_log_name[FN_REFLEN]; int exit_code; int consistent_binlog_pos= 0; - MY_INIT("mysqldump"); + MY_INIT(argv[0]); + sf_leaking_memory=1; /* don't report memory leaks on early exits */ compatible_mode_normal_str[0]= 0; default_charset= (char *)mysql_universal_client_charset; bzero((char*) &ignore_table, sizeof(ignore_table)); @@ -5329,6 +5528,7 @@ int main(int argc, char **argv) free_resources(); exit(exit_code); } + sf_leaking_memory=0; /* from now on we cleanup properly */ /* Disable comments in xml mode if 'comments' option is not explicitly used. @@ -5353,32 +5553,55 @@ int main(int argc, char **argv) if (!path) write_header(md_result_file, *argv); + if (opt_slave_data && do_stop_slave_sql(mysql)) + goto err; + if (opt_single_transaction && opt_master_data) { /* See if we can avoid FLUSH TABLES WITH READ LOCK (MariaDB 5.3+). */ consistent_binlog_pos= check_consistent_binlog_pos(NULL, NULL); } - if ((opt_lock_all_tables || (opt_master_data && !consistent_binlog_pos)) && + if ((opt_lock_all_tables || (opt_master_data && !consistent_binlog_pos) || + (opt_single_transaction && flush_logs)) && do_flush_tables_read_lock(mysql)) goto err; - if (opt_single_transaction && start_transaction(mysql)) - goto err; - if (opt_delete_master_logs) + + /* + Flush logs before starting transaction since + this causes implicit commit starting mysql-5.5. + */ + if (opt_lock_all_tables || opt_master_data || + (opt_single_transaction && flush_logs) || + opt_delete_master_logs) { - if (mysql_refresh(mysql, REFRESH_LOG) || - get_bin_log_name(mysql, bin_log_name, sizeof(bin_log_name))) - goto err; + if (flush_logs || opt_delete_master_logs) + { + if (mysql_refresh(mysql, REFRESH_LOG)) + goto err; + verbose_msg("-- main : logs flushed successfully!\n"); + } + + /* Not anymore! That would not be sensible. */ flush_logs= 0; } - if (opt_lock_all_tables || opt_master_data) + + if (opt_delete_master_logs) { - if (flush_logs && mysql_refresh(mysql, REFRESH_LOG)) + if (get_bin_log_name(mysql, bin_log_name, sizeof(bin_log_name))) goto err; - flush_logs= 0; /* not anymore; that would not be sensible */ } + + if (opt_single_transaction && start_transaction(mysql)) + goto err; + + /* Add 'STOP SLAVE to beginning of dump */ + if (opt_slave_apply && add_stop_slave()) + goto err; if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos)) goto err; + if (opt_slave_data && do_show_slave_status(mysql)) + goto err; if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */ goto err; @@ -5406,6 +5629,14 @@ int main(int argc, char **argv) dump_databases(argv); } + /* if --dump-slave , start the slave sql thread */ + if (opt_slave_data && do_start_slave_sql(mysql)) + goto err; + + /* add 'START SLAVE' to end of dump */ + if (opt_slave_apply && add_slave_statements()) + goto err; + /* ensure dumped data flushed */ if (md_result_file && fflush(md_result_file)) { @@ -5418,7 +5649,7 @@ int main(int argc, char **argv) goto err; #ifdef HAVE_SMEM - my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); + my_free(shared_memory_base_name); #endif /* No reason to explicitely COMMIT the transaction, neither to explicitely |