summaryrefslogtreecommitdiff
path: root/client/mysqldump.c
diff options
context:
space:
mode:
Diffstat (limited to 'client/mysqldump.c')
-rw-r--r--client/mysqldump.c313
1 files changed, 300 insertions, 13 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 5ecf334c9f7..dc7527c9c73 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -50,6 +50,7 @@
#include "mysql.h"
#include "mysql_version.h"
#include "mysqld_error.h"
+#include "../sql/ha_ndbcluster_tables.h"
/* Exit codes */
@@ -95,7 +96,10 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
opt_complete_insert= 0, opt_drop_database= 0,
- opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1;
+ opt_replace_into= 0,
+ opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1,
+ opt_events= 0,
+ opt_alltspcs=0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*mysql=0;
static my_bool insert_pat_inited=0;
@@ -132,7 +136,6 @@ static CHARSET_INFO *charset_info= &my_charset_latin1;
const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace";
/* have we seen any VIEWs during table scanning? */
my_bool seen_views= 0;
-
const char *compatible_mode_names[]=
{
"MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
@@ -163,6 +166,10 @@ static struct my_option my_long_options[] =
"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-tablespaces", 'Y',
+ "Dump all the tablespaces.",
+ (gptr*) &opt_alltspcs, (gptr*) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ 0, 0},
{"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
(gptr*) &opt_drop_database, (gptr*) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
0},
@@ -227,6 +234,9 @@ static struct my_option my_long_options[] =
{"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, 1, 0, 0, 0, 0, 0},
+ {"events", 'E', "Dump events.",
+ (gptr*) &opt_events, (gptr*) &opt_events, 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,
@@ -343,6 +353,9 @@ static struct my_option my_long_options[] =
{"quote-names",'Q', "Quote table and column names with backticks (`).",
(gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
0, 0},
+ {"replace", OPT_MYSQL_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
+ (gptr*) &opt_replace_into, (gptr*) &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},
@@ -1260,9 +1273,136 @@ static void print_xml_row(FILE *xml_file, const char *row_name,
check_io(xml_file);
}
+
+/*
+ create_delimiter
+ Generate a new (null-terminated) string that does not exist in query
+ and is therefore suitable for use as a query delimiter. Store this
+ delimiter in delimiter_buff .
+
+ This is quite simple in that it doesn't even try to parse statements as an
+ interpreter would. It merely returns a string that is not in the query, which
+ is much more than adequate for constructing a delimiter.
+
+ RETURN
+ ptr to the delimiter on Success
+ NULL on Failure
+*/
+static char *create_delimiter(char *query, char *delimiter_buff,
+ int delimiter_max_size)
+{
+ int proposed_length;
+ char *presence;
+
+ delimiter_buff[0]= ';'; /* start with one semicolon, and */
+
+ for (proposed_length= 2; proposed_length < delimiter_max_size;
+ delimiter_max_size++) {
+
+ delimiter_buff[proposed_length-1]= ';'; /* add semicolons, until */
+ delimiter_buff[proposed_length]= '\0';
+
+ presence = strstr(query, delimiter_buff);
+ if (presence == NULL) { /* the proposed delimiter is not in the query. */
+ return delimiter_buff;
+ }
+
+ }
+ return NULL; /* but if we run out of space, return nothing at all. */
+}
+
+
+/*
+ dump_events_for_db
+ -- retrieves list of events for a given db, and prints out
+ the CREATE EVENT statement into the output (the dump).
+
+ RETURN
+ 0 Success
+ 1 Error
+*/
+static uint dump_events_for_db(char *db)
+{
+ char query_buff[QUERY_LENGTH];
+ char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
+ char *event_name;
+ char delimiter[QUERY_LENGTH], *delimit_test;
+ FILE *sql_file= md_result_file;
+ MYSQL_RES *event_res, *event_list_res;
+ MYSQL_ROW row, event_list_row;
+ DBUG_ENTER("dump_events_for_db");
+ DBUG_PRINT("enter", ("db: '%s'", db));
+
+ mysql_real_escape_string(sock, db_name_buff, db, strlen(db));
+
+ /* nice comments */
+ if (opt_comments)
+ fprintf(sql_file, "\n--\n-- Dumping events for database '%s'\n--\n", db);
+
+ /*
+ not using "mysql_query_with_error_report" because we may have not
+ enough privileges to lock mysql.events.
+ */
+ if (lock_tables)
+ mysql_query(sock, "LOCK TABLES mysql.event READ");
+
+ if (mysql_query_with_error_report(sock, &event_list_res, "show events"))
+ {
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
+
+ strcpy(delimiter, ";");
+ if (mysql_num_rows(event_list_res) > 0)
+ {
+ while ((event_list_row= mysql_fetch_row(event_list_res)) != NULL)
+ {
+ event_name= quote_name(event_list_row[1], name_buff, 0);
+ DBUG_PRINT("info", ("retrieving CREATE EVENT for %s", name_buff));
+ my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE EVENT %s",
+ event_name);
+
+ if (mysql_query_with_error_report(sock, &event_res, query_buff))
+ DBUG_RETURN(1);
+
+ while ((row= mysql_fetch_row(event_res)) != NULL)
+ {
+ /*
+ if the user has EXECUTE privilege he can see event names, but not the
+ event body!
+ */
+ if (strlen(row[2]) != 0)
+ {
+ if (opt_drop)
+ fprintf(sql_file, "/*!50106 DROP EVENT IF EXISTS %s */%s\n",
+ event_name, delimiter);
+
+ delimit_test= create_delimiter(row[2], delimiter, sizeof(delimiter));
+ if (delimit_test == NULL) {
+ fprintf(stderr, "%s: Warning: Can't dump event '%s'\n",
+ event_name, my_progname);
+ DBUG_RETURN(1);
+ }
+
+ fprintf(sql_file, "DELIMITER %s\n", delimiter);
+ fprintf(sql_file, "/*!50106 %s */ %s\n", row[2], delimiter);
+ }
+ } /* end of event printing */
+ } /* end of list of events */
+ fprintf(sql_file, "DELIMITER ;\n");
+ mysql_free_result(event_res);
+ }
+ mysql_free_result(event_list_res);
+
+ if (lock_tables)
+ VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
+ DBUG_RETURN(0);
+}
+
+
/*
dump_routines_for_db
- -- retrievs list of routines for a given db, and prints out
+ -- retrieves list of routines for a given db, and prints out
the CREATE PROCEDURE definition into the output (the dump).
This function has logic to print the appropriate syntax depending on whether
@@ -1275,7 +1415,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name,
static uint dump_routines_for_db(char *db)
{
- char query_buff[512];
+ char query_buff[QUERY_LENGTH];
const char *routine_type[]= {"FUNCTION", "PROCEDURE"};
char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
char *routine_name;
@@ -1316,9 +1456,9 @@ static uint dump_routines_for_db(char *db)
while ((routine_list_row= mysql_fetch_row(routine_list_res)))
{
+ routine_name= quote_name(routine_list_row[1], name_buff, 0);
DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i],
name_buff));
- routine_name= quote_name(routine_list_row[1], name_buff, 0);
my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s",
routine_type[i], routine_name);
@@ -1430,8 +1570,8 @@ static uint get_table_structure(char *table, char *db, char *table_type,
my_ulonglong num_fields;
char *result_table, *opt_quoted_table;
const char *insert_option;
- char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
- char table_buff2[NAME_LEN*2+3], query_buff[512];
+ char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
+ char table_buff2[NAME_LEN*2+3], query_buff[QUERY_LENGTH];
FILE *sql_file = md_result_file;
int len;
MYSQL_RES *result;
@@ -1639,7 +1779,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
*/
if (write_data)
{
- dynstr_append_mem(&insert_pat, "INSERT ", 7);
+ if (opt_replace_into)
+ dynstr_append_mem(&insert_pat, "REPLACE ", 8);
+ else
+ dynstr_append_mem(&insert_pat, "INSERT ", 7);
dynstr_append(&insert_pat, insert_option);
dynstr_append_mem(&insert_pat, "INTO ", 5);
dynstr_append(&insert_pat, opt_quoted_table);
@@ -1710,7 +1853,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (write_data)
{
- dynstr_append_mem(&insert_pat, "INSERT ", 7);
+ if (opt_replace_into)
+ dynstr_append_mem(&insert_pat, "REPLACE ", 8);
+ else
+ dynstr_append_mem(&insert_pat, "INSERT ", 7);
dynstr_append(&insert_pat, insert_option);
dynstr_append_mem(&insert_pat, "INTO ", 5);
dynstr_append(&insert_pat, result_table);
@@ -1927,7 +2073,7 @@ static void dump_triggers_for_table (char *table, char *db)
{
char *result_table;
char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
- char query_buff[512];
+ char query_buff[QUERY_LENGTH];
uint old_opt_compatible_mode=opt_compatible_mode;
FILE *sql_file = md_result_file;
MYSQL_RES *result;
@@ -2581,6 +2727,130 @@ static char *getTableName(int reset)
} /* getTableName */
+/*
+ dump all logfile groups and tablespaces
+*/
+
+static int dump_all_tablespaces()
+{
+ MYSQL_ROW row;
+ MYSQL_RES *tableres;
+ char buf[FN_REFLEN];
+ int first;
+
+ if (mysql_query_with_error_report(sock, &tableres,
+ "SELECT DISTINCT"
+ " LOGFILE_GROUP_NAME,"
+ " FILE_NAME,"
+ " TOTAL_EXTENTS,"
+ " INITIAL_SIZE,"
+ " ENGINE"
+ " FROM INFORMATION_SCHEMA.FILES"
+ " WHERE FILE_TYPE = \"UNDO LOG\""
+ " ORDER BY LOGFILE_GROUP_NAME"))
+ return 1;
+
+ buf[0]= 0;
+ while ((row= mysql_fetch_row(tableres)))
+ {
+ if (strcmp(buf, row[0]) != 0)
+ 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);
+ }
+ fprintf(md_result_file, "\nCREATE");
+ }
+ else
+ {
+ fprintf(md_result_file, "\nALTER");
+ }
+ fprintf(md_result_file,
+ " LOGFILE GROUP %s\n"
+ " ADD UNDOFILE '%s'\n",
+ row[0],
+ row[1]);
+ if (first)
+ {
+ fprintf(md_result_file,
+ " UNDO_BUFFER_SIZE %s\n",
+ row[2]);
+ }
+ fprintf(md_result_file,
+ " INITIAL_SIZE %s\n"
+ " ENGINE=%s;\n",
+ row[3],
+ row[4]);
+ check_io(md_result_file);
+ if (first)
+ {
+ first= 0;
+ strxmov(buf, row[0], NullS);
+ }
+ }
+
+ if (mysql_query_with_error_report(sock, &tableres,
+ "SELECT DISTINCT"
+ " TABLESPACE_NAME,"
+ " FILE_NAME,"
+ " LOGFILE_GROUP_NAME,"
+ " EXTENT_SIZE,"
+ " INITIAL_SIZE,"
+ " ENGINE"
+ " FROM INFORMATION_SCHEMA.FILES"
+ " WHERE FILE_TYPE = \"DATAFILE\""
+ " ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME"))
+ return 1;
+
+ buf[0]= 0;
+ while ((row= mysql_fetch_row(tableres)))
+ {
+ if (strcmp(buf, row[0]) != 0)
+ 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);
+ }
+ fprintf(md_result_file, "\nCREATE");
+ }
+ else
+ {
+ fprintf(md_result_file, "\nALTER");
+ }
+ fprintf(md_result_file,
+ " TABLESPACE %s\n"
+ " ADD DATAFILE '%s'\n",
+ row[0],
+ row[1]);
+ if (first)
+ {
+ fprintf(md_result_file,
+ " USE LOGFILE GROUP %s\n"
+ " EXTENT_SIZE %s\n",
+ row[2],
+ row[3]);
+ }
+ fprintf(md_result_file,
+ " INITIAL_SIZE %s\n"
+ " ENGINE=%s;\n",
+ row[4],
+ row[5]);
+ check_io(md_result_file);
+ if (first)
+ {
+ first= 0;
+ strxmov(buf, row[0], NullS);
+ }
+ }
+ return 0;
+}
+
static int dump_all_databases()
{
MYSQL_ROW row;
@@ -2725,6 +2995,8 @@ static int dump_all_tables_in_db(char *database)
afterdot= strmov(hash_key, database);
*afterdot++= '.';
+ if (!strcmp(database, NDB_REP_DB)) /* Skip cluster internal database */
+ return 0;
if (init_dumping(database))
return 1;
if (opt_xml)
@@ -2762,6 +3034,12 @@ static int dump_all_tables_in_db(char *database)
dump_triggers_for_table(table, database);
}
}
+ if (opt_events && !opt_xml &&
+ mysql_get_server_version(sock) >= 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)
{
@@ -2909,11 +3187,11 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
DBUG_ENTER("dump_selected_tables");
if (init_dumping(db))
- return 1;
+ DBUG_RETURN(1);
init_alloc_root(&root, 8192, 0);
if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
- exit(EX_EOM);
+ exit(EX_EOM);
init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024);
for (; tables > 0 ; tables-- , table_names++)
@@ -2924,7 +3202,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
/* Add found table name to lock_tables_query */
if (lock_tables)
{
- dynstr_append(&lock_tables_query, quote_name(*pos, table_buff, 1));
+ dynstr_append(&lock_tables_query, quote_name(*pos, table_buff, 1));
dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,");
}
pos++;
@@ -2972,6 +3250,12 @@ 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(sock) >= 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)
@@ -3576,6 +3860,9 @@ int main(int argc, char **argv)
if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */
goto err;
+ if (opt_alltspcs)
+ dump_all_tablespaces();
+
if (opt_alldbs)
dump_all_databases();
else if (argc > 1 && !opt_databases)