diff options
Diffstat (limited to 'client/mysqldump.c')
-rw-r--r-- | client/mysqldump.c | 691 |
1 files changed, 321 insertions, 370 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c index d7d54a13c57..a6eaf1794fd 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -33,9 +33,10 @@ ** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee> ** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up ** and adapted to mysqldump 05/11/01 by Jani Tolonen +** Added --single-transaction option 06/06/2002 by Peter Zaitsev */ -#define DUMP_VERSION "8.22" +#define DUMP_VERSION "9.07" #include <my_global.h> #include <my_sys.h> @@ -46,7 +47,6 @@ #include "mysql.h" #include "mysql_version.h" #include "mysqld_error.h" -#include <getopt.h> /* Exit codes */ @@ -64,6 +64,9 @@ #define SHOW_EXTRA 5 #define QUOTE_CHAR '`' +/* Size of buffer for dump's select query */ +#define QUERY_LENGTH 1536 + static char *add_load_option(char *ptr, const char *object, const char *statement); @@ -73,7 +76,8 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick=0, extended_insert = 0, ignore=0,opt_drop=0,opt_keywords=0,opt_lock=0,opt_compress=0, opt_delayed=0,create_options=0,opt_quoted=0,opt_databases=0, opt_alldbs=0,opt_create_db=0,opt_first_slave=0, - opt_autocommit=0,opt_master_data,opt_disable_keys=0,opt_xml=0; + opt_autocommit=0,opt_master_data,opt_disable_keys=0,opt_xml=0, + tty_password=0,opt_single_transaction=0; static MYSQL mysql_connection,*sock=0; static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *current_host=0,*path=0,*fields_terminated=0, @@ -84,75 +88,161 @@ static my_string opt_mysql_unix_port=0; static int first_error=0; extern ulong net_buffer_length; static DYNAMIC_STRING extended_row; -#include "sslopt-vars.h" +#include <sslopt-vars.h> FILE *md_result_file; -static struct option long_options[] = +static struct my_option my_long_options[] = { - {"all-databases", no_argument, 0, 'A'}, - {"all", no_argument, 0, 'a'}, - {"add-drop-table", no_argument, 0, OPT_DROP}, - {"add-locks", no_argument, 0, OPT_LOCKS}, - {"allow-keywords", no_argument, 0, OPT_KEYWORDS}, - {"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR}, - {"complete-insert", no_argument, 0, 'c'}, - {"compress", no_argument, 0, 'C'}, - {"databases", no_argument, 0, 'B'}, - {"debug", optional_argument, 0, '#'}, - {"default-character-set", required_argument, 0, OPT_DEFAULT_CHARSET}, - {"delayed-insert", no_argument, 0, OPT_DELAYED}, - {"disable-keys", no_argument, 0, 'K'}, - {"extended-insert", no_argument, 0, 'e'}, - {"fields-terminated-by", required_argument, 0, (int) OPT_FTB}, - {"fields-enclosed-by", required_argument, 0, (int) OPT_ENC}, - {"fields-optionally-enclosed-by", required_argument, 0, (int) OPT_O_ENC}, - {"fields-escaped-by", required_argument, 0, (int) OPT_ESC}, - {"first-slave", no_argument, 0, 'x'}, - {"flush-logs", no_argument, 0, 'F'}, - {"force", no_argument, 0, 'f'}, - {"help", no_argument, 0, '?'}, - {"host", required_argument, 0, 'h'}, - {"lines-terminated-by", required_argument, 0, (int) OPT_LTB}, - {"lock-tables", no_argument, 0, 'l'}, - {"master-data", no_argument, 0, OPT_MASTER_DATA}, - {"no-autocommit", no_argument, 0, OPT_AUTOCOMMIT}, - {"no-create-db", no_argument, 0, 'n'}, - {"no-create-info", no_argument, 0, 't'}, - {"no-data", no_argument, 0, 'd'}, - {"opt", no_argument, 0, OPT_OPTIMIZE}, - {"password", optional_argument, 0, 'p'}, + {"all-databases", 'A', + "Dump all the databases. This will be same as --databases with all databases selected.", + (gptr*) &opt_alldbs, (gptr*) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, + {"all", 'a', "Include all MySQL specific create options.", + (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 0, + 0, 0, 0, 0, 0}, + {"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.", + (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + 0}, + {"add-locks", OPT_LOCKS, "Add locks around insert statements.", + (gptr*) &opt_lock, (gptr*) &opt_lock, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + 0}, + {"allow-keywords", OPT_KEYWORDS, + "Allow creation of column names that are keywords.", (gptr*) &opt_keywords, + (gptr*) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"character-sets-dir", OPT_CHARSETS_DIR, + "Directory where character sets are", (gptr*) &charsets_dir, + (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"complete-insert", 'c', "Use complete insert statements.", (gptr*) &cFlag, + (gptr*) &cFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"compress", 'C', "Use compression in server/client protocol.", + (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + 0, 0, 0}, + {"databases", 'B', + "To dump several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames. 'USE db_name;' will be included in the output.", + (gptr*) &opt_databases, (gptr*) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, + 0, 0, 0, 0}, + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"default-character-set", OPT_DEFAULT_CHARSET, + "Set the default character set.", (gptr*) &default_charset, + (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED.", + (gptr*) &opt_delayed, (gptr*) &opt_delayed, 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.", (gptr*) &opt_disable_keys, + (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"extended-insert", 'e', + "Allows utilization of the new, much faster INSERT syntax.", + (gptr*) &extended_insert, (gptr*) &extended_insert, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, + {"fields-terminated-by", OPT_FTB, + "Fields in the textfile are terminated by ...", (gptr*) &fields_terminated, + (gptr*) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"fields-enclosed-by", OPT_ENC, + "Fields in the importfile are enclosed by ...", (gptr*) &enclosed, + (gptr*) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, + {"fields-optionally-enclosed-by", OPT_O_ENC, + "Fields in the i.file are opt. enclosed by ...", (gptr*) &opt_enclosed, + (gptr*) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, + {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...", + (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"first-slave", 'x', "Locks all tables across all databases.", + (gptr*) &opt_first_slave, (gptr*) &opt_first_slave, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, + {"flush-logs", 'F', "Flush logs file in server before starting dump.", + (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, + {"force", 'f', "Continue even if we get an sql-error.", + (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, + {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, + NO_ARG, 0, 0, 0, 0, 0, 0}, + {"host", 'h', "Connect to host.", (gptr*) ¤t_host, + (gptr*) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...", + (gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables, + (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"master-data", OPT_MASTER_DATA, + "This will cause the master position and filename to be appended to your output. This will automagically enable --first-slave.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"no-autocommit", OPT_AUTOCOMMIT, + "Wrap tables with autocommit/commit statements.", + (gptr*) &opt_autocommit, (gptr*) &opt_autocommit, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, + {"single-transaction", OPT_TRANSACTION, + "Dump all tables in single transaction to get consistent snapshot. Mutually exclusive with --lock-tables.", + (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, + {"no-create-db", 'n', + "'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given.}", + (gptr*) &opt_create_db, (gptr*) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0, + 0, 0, 0, 0}, + {"no-create-info", 't', "Don't write table creation info.", + (gptr*) &tFlag, (gptr*) &tFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"no-data", 'd', "No row information.", (gptr*) &dFlag, (gptr*) &dFlag, 0, + GET_BOOL, NO_ARG, 0, 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}, + {"opt", OPT_OPTIMIZE, + "Same as --add-drop-table --add-locks --all --quick --extended-insert --lock-tables --disable-keys", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"password", 'p', + "Password to use when connecting to server. If password is not given it's solicited on the tty.", + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ - {"pipe", no_argument, 0, 'W'}, + {"pipe", 'W', "Use named pipes to connect to server", 0, 0, 0, GET_NO_ARG, + NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"port", required_argument, 0, 'P'}, - {"quick", no_argument, 0, 'q'}, - {"quote-names", no_argument, 0, 'Q'}, - {"result-file", required_argument, 0, 'r'}, - {"set-variable", required_argument, 0, 'O'}, - {"socket", required_argument, 0, 'S'}, -#include "sslopt-longopts.h" - {"tab", required_argument, 0, 'T'}, - {"tables", no_argument, 0, OPT_TABLES}, + {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + 0}, + {"quick", 'q', "Don't buffer query, dump directly to stdout.", + (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"quote-names",'Q', "Quote table and column names with a `", + (gptr*) &opt_quoted, (gptr*) &opt_quoted, 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}, + {"socket", 'S', "Socket file to use for connection.", + (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#include <sslopt-longopts.h> + {"tab",'T', + "Creates tab separated textfile for each table to given path. (creates .sql and .txt files). NOTE: This only works if mysqldump is run on the same machine as the mysqld daemon.", + (gptr*) &path, (gptr*) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"tables", OPT_TABLES, "Overrides option --databases (-B).", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DONT_ALLOW_USER_CHANGE - {"user", required_argument, 0, 'u'}, + {"user", 'u', "User for login if not current user.", + (gptr*) ¤t_user, (gptr*) ¤t_user, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, #endif - {"verbose", no_argument, 0, 'v'}, - {"version", no_argument, 0, 'V'}, - {"where", required_argument, 0, 'w'}, - {"xml", no_argument, 0, 'X'}, - {0, 0, 0, 0} + {"verbose", 'v', "Print info about the various stages.", + (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"version",'V', "Output version information and exit.", 0, 0, 0, + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"where", 'w', "Dump only selected records; QUOTES mandatory!", + (gptr*) &where, (gptr*) &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}, + {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "", + (gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0, + GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096, 1024*1024L*1024L, + MALLOC_OVERHEAD, 1024, 0}, + {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "", + (gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0, + GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L, + MALLOC_OVERHEAD-1024, 1024, 0}, + {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; static const char *load_default_groups[]= { "mysqldump","client",0 }; -CHANGEABLE_VAR md_changeable_vars[] = { - { "max_allowed_packet", (long*) &max_allowed_packet,24*1024*1024,4096, - 16*1024L*1024L,MALLOC_OVERHEAD,1024}, - { "net_buffer_length", (long*) &net_buffer_length,1024*1024L-1025,4096, - 16*1024L*1024L,MALLOC_OVERHEAD+1024,1024}, - { 0, 0, 0, 0, 0, 0, 0} -}; - static void safe_exit(int error); static void write_header(FILE *sql_file, char *db_name); static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, @@ -173,119 +263,41 @@ static void print_version(void) } /* print_version */ +static void short_usage_sub(void) +{ + printf("Usage: %s [OPTIONS] database [tables]\n", my_progname); + printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n", + my_progname); + printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname); +} + static void usage(void) { - uint i; print_version(); puts("By Igor Romanenko, Monty, Jani & Sinisa"); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); puts("Dumping definition and data mysql database or table"); - printf("Usage: %s [OPTIONS] database [tables]\n", my_progname); - printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n", - my_progname); - printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname); - printf("\n\ - -A, --all-databases Dump all the databases. This will be same as\n\ - --databases with all databases selected.\n\ - -a, --all Include all MySQL specific create options.\n\ - -#, --debug=... Output debug log. Often this is 'd:t:o,filename`.\n\ - --character-sets-dir=...\n\ - Directory where character sets are\n\ - -?, --help Display this help message and exit.\n\ - -B, --databases To dump several databases. Note the difference in\n\ - usage; In this case no tables are given. All name\n\ - arguments are regarded as databasenames.\n\ - 'USE db_name;' will be included in the output\n\ - -c, --complete-insert Use complete insert statements.\n\ - -C, --compress Use compression in server/client protocol.\n\ - --default-character-set=...\n\ - Set the default character set\n\ - -e, --extended-insert Allows utilization of the new, much faster\n\ - INSERT syntax.\n\ - --add-drop-table Add a 'drop table' before each create.\n\ - --add-locks Add locks around insert statements.\n\ - --allow-keywords Allow creation of column names that are keywords.\n\ - --delayed-insert Insert rows with INSERT DELAYED.\n\ - --master-data This will cause the master position and filename to \n\ - be appended to your output. This will automagically \n\ - enable --first-slave.\n\ - -F, --flush-logs Flush logs file in server before starting dump.\n\ - -f, --force Continue even if we get an sql-error.\n\ - -h, --host=... Connect to host.\n"); -puts("\ - -l, --lock-tables Lock all tables for read.\n\ - --no-autocommit Wrap tables with autocommit/commit statements.\n\ - -K, --disable-keys '/*!40000 ALTER TABLE tb_name DISABLE KEYS */;\n\ - and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */;\n\ - will be put in the output.\n\ - -n, --no-create-db 'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;'\n\ - will not be put in the output. The above line will\n\ - be added otherwise, if --databases or\n\ - --all-databases option was given.\n\ - -t, --no-create-info Don't write table creation info.\n\ - -d, --no-data No row information.\n\ - -O, --set-variable var=option\n\ - give a variable a value. --help lists variables\n\ - --opt Same as --add-drop-table --add-locks --all --quick\n\ - --extended-insert --lock-tables --disable-keys\n\ - -p, --password[=...] Password to use when connecting to server.\n\ - If password is not given it's solicited on the tty.\n"); -#ifdef __WIN__ - puts("-W, --pipe Use named pipes to connect to server"); -#endif - printf("\ - -P, --port=... Port number to use for connection.\n\ - -q, --quick Don't buffer query, dump directly to stdout.\n\ - -Q, --quote-names Quote table and column names with `\n\ - -r, --result-file=... Direct output to a given file. This option should be\n\ - used in MSDOS, because it prevents new line '\\n'\n\ - from being converted to '\\n\\r' (newline + carriage\n\ - return).\n\ - -S, --socket=... Socket file to use for connection.\n\ - --tables Overrides option --databases (-B).\n"); -#include "sslopt-usage.h" - printf("\ - -T, --tab=... Creates tab separated textfile for each table to\n\ - given path. (creates .sql and .txt files).\n\ - NOTE: This only works if mysqldump is run on\n\ - the same machine as the mysqld daemon.\n"); -#ifndef DONT_ALLOW_USER_CHANGE - printf("\ - -u, --user=# User for login if not current user.\n"); -#endif - printf("\ - -v, --verbose Print info about the various stages.\n\ - -V, --version Output version information and exit.\n\ - -w, --where= dump only selected records; QUOTES mandatory!\n\ - -X, --xml dump a database as well formed XML\n\ - -x, --first-slave Locks all tables across all databases.\n\ - EXAMPLES: \"--where=user=\'jimf\'\" \"-wuserid>1\" \"-wuserid<1\"\n\ - Use -T (--tab=...) with --fields-...\n\ - --fields-terminated-by=...\n\ - Fields in the textfile are terminated by ...\n\ - --fields-enclosed-by=...\n\ - Fields in the importfile are enclosed by ...\n\ - --fields-optionally-enclosed-by=...\n\ - Fields in the i.file are opt. enclosed by ...\n\ - --fields-escaped-by=...\n\ - Fields in the i.file are escaped by ...\n\ - --lines-terminated-by=...\n\ - Lines in the i.file are terminated by ...\n\ -"); + short_usage_sub(); print_defaults("my",load_default_groups); - - printf("\nPossible variables for option --set-variable (-O) are:\n"); - for (i=0 ; md_changeable_vars[i].name ; i++) - printf("%-20s current value: %lu\n", - md_changeable_vars[i].name, - (ulong) *md_changeable_vars[i].varptr); + my_print_help(my_long_options); + my_print_variables(my_long_options); } /* usage */ +static void short_usage(void) +{ + short_usage_sub(); + printf("For more options, use %s --help\n", my_progname); +} + + static void write_header(FILE *sql_file, char *db_name) { if (opt_xml) + { fprintf(sql_file,"<?xml version=\"1.0\"?>\n"); + fprintf(sql_file,"<mysqldump>\n"); + } else { fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION); @@ -299,182 +311,99 @@ static void write_header(FILE *sql_file, char *db_name) return; } /* write_header */ - -static int get_options(int *argc,char ***argv) +static void write_footer(FILE *sql_file) { - int c,option_index; - my_bool tty_password=0; + if (opt_xml) + fprintf(sql_file,"</mysqldump>"); + fputs("\n", sql_file); +} /* write_footer */ - md_result_file=stdout; - load_defaults("my",load_default_groups,argc,argv); - set_all_changeable_vars(md_changeable_vars); - while ((c=getopt_long(*argc,*argv, - "#::p::h:u:O:P:r:S:T:EBaAcCdefFKlnqQtvVw:?IxX", - long_options, &option_index)) != EOF) - { - switch(c) { - case OPT_MASTER_DATA: - opt_master_data=1; - opt_first_slave=1; - break; - case OPT_AUTOCOMMIT: - opt_autocommit=1; - break; - case 'a': - create_options=1; - break; - case 'e': - extended_insert=1; - break; - case 'A': - opt_alldbs=1; - break; - case OPT_DEFAULT_CHARSET: - default_charset= optarg; - break; - case OPT_CHARSETS_DIR: - charsets_dir= optarg; - break; - case 'f': - ignore_errors=1; - break; - case 'F': - flush_logs=1; - break; - case 'h': - my_free(current_host,MYF(MY_ALLOW_ZERO_PTR)); - current_host=my_strdup(optarg,MYF(MY_WME)); - break; - case 'K': - opt_disable_keys=1; - break; - case 'n': - opt_create_db = 1; - break; -#ifndef DONT_ALLOW_USER_CHANGE - case 'u': - current_user=optarg; - break; -#endif - case 'O': - if (set_changeable_var(optarg, md_changeable_vars)) - { - usage(); - return(1); - } - break; - case 'p': - if (optarg) - { - char *start=optarg; - my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); - opt_password=my_strdup(optarg,MYF(MY_FAE)); - while (*optarg) *optarg++= 'x'; /* Destroy argument */ - if (*start) - start[1]=0; /* Cut length of argument */ - } - else - tty_password=1; - break; - case 'P': - opt_mysql_port= (unsigned int) atoi(optarg); - break; - case 'r': - if (!(md_result_file = my_fopen(optarg, O_WRONLY | O_BINARY, - MYF(MY_WME)))) - exit(1); - break; - case 'S': - opt_mysql_unix_port= optarg; - break; - case 'W': +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch(optid) { + case OPT_MASTER_DATA: + opt_master_data=1; + opt_first_slave=1; + break; + case 'p': + if (argument) + { + char *start=argument; + my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); + opt_password=my_strdup(argument,MYF(MY_FAE)); + while (*argument) *argument++= 'x'; /* Destroy argument */ + if (*start) + start[1]=0; /* Cut length of argument */ + } + else + tty_password=1; + break; + case 'r': + if (!(md_result_file = my_fopen(argument, O_WRONLY | O_BINARY, + MYF(MY_WME)))) + exit(1); + break; + case 'W': #ifdef __WIN__ - opt_mysql_unix_port=MYSQL_NAMEDPIPE; + opt_mysql_unix_port=MYSQL_NAMEDPIPE; #endif - break; - case 'T': - path= optarg; - opt_disable_keys=0; - break; - case 'B': - opt_databases = 1; - break; - case '#': - DBUG_PUSH(optarg ? optarg : "d:t:o"); - break; - case 'c': cFlag=1; break; - case 'C': - opt_compress=1; - break; - case 'd': dFlag=1; break; - case 'l': lock_tables=1; break; - case 'q': quick=1; break; - case 'Q': opt_quoted=1; break; - case 't': tFlag=1; break; - case 'v': verbose=1; break; - case 'V': print_version(); exit(0); - case 'w': - where=optarg; - break; - case 'X': - opt_xml = 1; - opt_disable_keys=0; - break; - case 'x': - opt_first_slave=1; - break; - default: - fprintf(stderr,"%s: Illegal option character '%c'\n",my_progname,opterr); - /* Fall throught */ - case 'I': - case '?': - usage(); - exit(0); - case (int) OPT_FTB: - fields_terminated= optarg; - break; - case (int) OPT_LTB: - lines_terminated= optarg; - break; - case (int) OPT_ENC: - enclosed= optarg; - break; - case (int) OPT_O_ENC: - opt_enclosed= optarg; - break; - case (int) OPT_ESC: - escaped= optarg; - break; - case (int) OPT_DROP: - opt_drop=1; - break; - case (int) OPT_KEYWORDS: - opt_keywords=1; - break; - case (int) OPT_LOCKS: - opt_lock=1; - break; - case (int) OPT_OPTIMIZE: - extended_insert=opt_drop=opt_lock=lock_tables=quick=create_options= - opt_disable_keys=1; - break; - case (int) OPT_DELAYED: - opt_delayed=1; - break; - case (int) OPT_TABLES: - opt_databases=0; - break; -#include "sslopt-case.h" - } + break; + case 'T': + opt_disable_keys=0; + break; + case '#': + DBUG_PUSH(argument ? argument : "d:t:o"); + break; +#include <sslopt-case.h> + case 'V': print_version(); exit(0); + case 'X': + opt_xml = 1; + opt_disable_keys=0; + break; + case 'I': + case '?': + usage(); + exit(0); + case (int) OPT_OPTIMIZE: + extended_insert=opt_drop=opt_lock=quick=create_options=opt_disable_keys= + lock_tables=1; + if (opt_single_transaction) lock_tables=0; + break; + case (int) OPT_TABLES: + opt_databases=0; + break; } + return 0; +} + + +static int get_options(int *argc, char ***argv) +{ + int ho_error; + + md_result_file= stdout; + load_defaults("my",load_default_groups,argc,argv); + + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) + exit(ho_error); + if (opt_delayed) opt_lock=0; /* Can't have lock with delayed */ if (!path && (enclosed || opt_enclosed || escaped || lines_terminated || fields_terminated)) { - fprintf(stderr, "%s: You must use option --tab with --fields-...\n", my_progname); + fprintf(stderr, + "%s: You must use option --tab with --fields-...\n", my_progname); return(1); } + + if (opt_single_transaction && lock_tables) + { + fprintf(stderr, "%s: You can't use --lock-tables and --single-transaction at the same time.\n", my_progname); + return(1); + } if (enclosed && opt_enclosed) { @@ -498,11 +427,9 @@ static int get_options(int *argc,char ***argv) if (set_default_charset_by_name(default_charset, MYF(MY_WME))) exit(1); } - (*argc)-=optind; - (*argv)+=optind; if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs)) { - usage(); + short_usage(); return 1; } if (tty_password) @@ -663,8 +590,7 @@ static uint getTableStructure(char *table, char* db) if (path) { char filename[FN_REFLEN], tmp_path[FN_REFLEN]; - strmov(tmp_path,path); - convert_dirname(tmp_path); + convert_dirname(tmp_path,path,NullS); sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4), O_WRONLY, MYF(MY_WME)); if (!sql_file) /* If file couldn't be opened */ @@ -741,8 +667,7 @@ static uint getTableStructure(char *table, char* db) if (path) { char filename[FN_REFLEN], tmp_path[FN_REFLEN]; - strmov(tmp_path,path); - convert_dirname(tmp_path); + convert_dirname(tmp_path,path,NullS); sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4), O_WRONLY, MYF(MY_WME)); if (!sql_file) /* If file couldn't be opened */ @@ -899,8 +824,6 @@ static uint getTableStructure(char *table, char* db) fputs(";\n", sql_file); } } - if (opt_disable_keys) - fprintf(sql_file,"\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",table_name); if (cFlag) { strpos=strmov(strpos,") VALUES "); @@ -969,7 +892,7 @@ static char *field_escape(char *to,const char *from,uint length) */ static void dumpTable(uint numFields, char *table) { - char query[1024], *end, buff[256],table_buff[NAME_LEN+3]; + char query[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3]; MYSQL_RES *res; MYSQL_FIELD *field; MYSQL_ROW row; @@ -980,14 +903,14 @@ static void dumpTable(uint numFields, char *table) if (path) { char filename[FN_REFLEN], tmp_path[FN_REFLEN]; - strmov(tmp_path,path); - convert_dirname(tmp_path); + convert_dirname(tmp_path,path,NullS); my_load_path(tmp_path, tmp_path, NULL); fn_format(filename, table, tmp_path, ".txt", 4); my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if filename wasn't deleted */ to_unix_path(filename); - sprintf(query, "SELECT * INTO OUTFILE '%s'", filename); + sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'", + filename); end= strend(query); if (replace) end= strmov(end, " REPLACE"); @@ -1018,7 +941,8 @@ static void dumpTable(uint numFields, char *table) if (!opt_xml) fprintf(md_result_file,"\n--\n-- Dumping data for table '%s'\n--\n", table); - sprintf(query, "SELECT * FROM %s", quote_name(table,table_buff)); + sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s", + quote_name(table,table_buff)); if (where) { if (!opt_xml) @@ -1026,7 +950,7 @@ static void dumpTable(uint numFields, char *table) strxmov(strend(query), " WHERE ",where,NullS); } if (!opt_xml) - fputs("\n\n", md_result_file); + fputs("\n", md_result_file); if (mysql_query(sock, query)) { DBerror(sock, "when retrieving data from server"); @@ -1051,6 +975,9 @@ static void dumpTable(uint numFields, char *table) return; } + if (opt_disable_keys) + fprintf(md_result_file,"/*!40000 ALTER TABLE %s DISABLE KEYS */;\n", + quote_name(table, table_buff)); if (opt_lock) fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", quote_name(table,table_buff)); @@ -1060,7 +987,7 @@ static void dumpTable(uint numFields, char *table) rownr=0; init_length=(uint) strlen(insert_pat)+4; if (opt_xml) - fprintf(md_result_file, "\t<%s>\n", table); + fprintf(md_result_file, "\t<table name=\"%s\">\n", table); if (opt_autocommit) fprintf(md_result_file, "set autocommit=0;\n"); @@ -1149,8 +1076,8 @@ static void dumpTable(uint numFields, char *table) /* change any strings ("inf","nan",..) into NULL */ char *ptr = row[i]; if (opt_xml) - fprintf(md_result_file, "\t\t<%s>%s</%s>\n", - field->name,!isalpha(*ptr) ?ptr: "NULL",field->name); + fprintf(md_result_file, "\t\t<field name=\"%s\">%s</field>\n", + field->name,!isalpha(*ptr) ?ptr: "NULL"); else fputs((!isalpha(*ptr)) ? ptr : "NULL", md_result_file); } @@ -1158,8 +1085,8 @@ static void dumpTable(uint numFields, char *table) else { if (opt_xml) - fprintf(md_result_file, "\t\t<%s>%s</%s>\n", - field->name, "NULL", field->name); + fprintf(md_result_file, "\t\t<field name=\"%s\">%s</field>\n", + field->name, "NULL"); else fputs("NULL", md_result_file); } @@ -1198,9 +1125,9 @@ static void dumpTable(uint numFields, char *table) fputs(");\n", md_result_file); } - /*XML - close table tag and supress regular output*/ + /* XML - close table tag and supress regular output */ if (opt_xml) - fprintf(md_result_file, "\t</%s>\n", table); + fprintf(md_result_file, "\t</table>\n"); else if (extended_insert && row_break) fputs(";\n", md_result_file); /* If not empty table */ fflush(md_result_file); @@ -1216,11 +1143,11 @@ static void dumpTable(uint numFields, char *table) safe_exit(EX_CONSCHECK); return; } - if (opt_disable_keys) - fprintf(md_result_file,"\n/*!40000 ALTER TABLE %s ENABLE KEYS */;\n", - quote_name(table,table_buff)); if (opt_lock) fputs("UNLOCK TABLES;\n", md_result_file); + if (opt_disable_keys) + fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n", + quote_name(table,table_buff)); if (opt_autocommit) fprintf(md_result_file, "commit;\n"); mysql_free_result(res); @@ -1232,7 +1159,7 @@ static void print_quoted_xml(FILE *output, char *fname, char *str, uint len) { const char *end; - fprintf(output, "\t\t<%s>", fname); + fprintf(output, "\t\t<field name=\"%s\">", fname); for (end = str + len; str != end; str++) { if (*str == '<') @@ -1246,7 +1173,7 @@ static void print_quoted_xml(FILE *output, char *fname, char *str, uint len) else fputc(*str, output); } - fprintf(output, "</%s>\n", fname); + fprintf(output, "</field>\n"); } static char *getTableName(int reset) @@ -1301,13 +1228,8 @@ static int dump_databases(char **db_names) int result=0; for ( ; *db_names ; db_names++) { - /*XML edit - add database element*/ - if (opt_xml) - fprintf(md_result_file, "<%s>\n", *db_names); if (dump_all_tables_in_db(*db_names)) result=1; - if (opt_xml) - fprintf(md_result_file, "</%s>\n", *db_names); } return result; } /* dump_databases */ @@ -1320,7 +1242,7 @@ static int init_dumping(char *database) DBerror(sock, "when selecting the database"); return 1; /* If --force */ } - if (!path) + if (!path && !opt_xml) { if (opt_databases || opt_alldbs) { @@ -1346,6 +1268,8 @@ static int dump_all_tables_in_db(char *database) if (init_dumping(database)) return 1; + if (opt_xml) + fprintf(md_result_file, "<database name=\"%s\">\n", database); if (lock_tables) { DYNAMIC_STRING query; @@ -1372,6 +1296,8 @@ static int dump_all_tables_in_db(char *database) if (!dFlag && numrows > 0) dumpTable(numrows,table); } + if (opt_xml) + fprintf(md_result_file, "</database>\n"); if (lock_tables) mysql_query(sock,"UNLOCK_TABLES"); return 0; @@ -1408,12 +1334,16 @@ static int dump_selected_tables(char *db, char **table_names, int tables) DBerror(sock, "when doing refresh"); /* We shall countinue here, if --force was given */ } + if (opt_xml) + fprintf(md_result_file, "<database name=\"%s\">\n", db); for (; tables > 0 ; tables-- , table_names++) { numrows = getTableStructure(*table_names, db); if (!dFlag && numrows > 0) dumpTable(numrows, *table_names); } + if (opt_xml) + fprintf(md_result_file, "</database>\n"); if (lock_tables) mysql_query(sock,"UNLOCK_TABLES"); return 0; @@ -1454,9 +1384,6 @@ int main(int argc, char **argv) MYSQL_RES *master; MY_INIT(argv[0]); - /* - ** Check out the args - */ if (get_options(&argc, &argv)) { my_end(0); @@ -1478,14 +1405,29 @@ int main(int argc, char **argv) return(first_error); } } + else if (opt_single_transaction) + { + /* There is no sense to start transaction if all tables are locked */ + if (mysql_query(sock, "BEGIN")) + { + my_printf_error(0, "Error: Couldn't execute 'BEGIN': %s", + MYF(0), mysql_error(sock)); + my_end(0); + return(first_error); + } + } if (opt_alldbs) dump_all_databases(); - /* Only one database and selected table(s) */ else if (argc > 1 && !opt_databases) + { + /* Only one database and selected table(s) */ dump_selected_tables(*argv, (argv + 1), (argc - 1)); - /* One or more databases, all tables */ + } else + { + /* One or more databases, all tables */ dump_databases(argv); + } if (opt_first_slave) { @@ -1493,14 +1435,13 @@ int main(int argc, char **argv) { if (mysql_query(sock, "SHOW MASTER STATUS") || !(master = mysql_store_result(sock))) - { my_printf_error(0, "Error: Couldn't execute 'SHOW MASTER STATUS': %s", MYF(0), mysql_error(sock)); - } else { row = mysql_fetch_row(master); - if(row[0] && row[1]) { + if (row[0] && row[1]) + { fprintf(md_result_file, "\n--\n-- Position to start replication from\n--\n\n"); fprintf(md_result_file, @@ -1512,18 +1453,28 @@ int main(int argc, char **argv) } } if (mysql_query(sock, "FLUSH MASTER")) - { my_printf_error(0, "Error: Couldn't execute 'FLUSH MASTER': %s", MYF(0), mysql_error(sock)); - } if (mysql_query(sock, "UNLOCK TABLES")) - { my_printf_error(0, "Error: Couldn't execute 'UNLOCK TABLES': %s", MYF(0), mysql_error(sock)); - } + } + else if (opt_single_transaction) /* Just to make it beautiful enough */ + { + /* + In case we were locking all tables, we did not start transaction + so there is no need to commit it. + */ + + /* This should just free locks as we did not change anything */ + if (mysql_query(sock, "COMMIT")) + { + my_printf_error(0, "Error: Couldn't execute 'COMMIT': %s", + MYF(0), mysql_error(sock)); + } } dbDisconnect(current_host); - fputs("\n", md_result_file); + write_footer(md_result_file); if (md_result_file != stdout) my_fclose(md_result_file, MYF(0)); my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); |