summaryrefslogtreecommitdiff
path: root/client/mysqldump.c
diff options
context:
space:
mode:
Diffstat (limited to 'client/mysqldump.c')
-rw-r--r--client/mysqldump.c1671
1 files changed, 1367 insertions, 304 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c
index fa6c21ed273..d755a17b815 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,14 +29,14 @@
** master/autocommit code by Brian Aker <brian@tangent.org>
** SSL by
** Andrei Errapart <andreie@no.spam.ee>
-** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee>
+** 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
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
*/
-#define DUMP_VERSION "10.11"
+#define DUMP_VERSION "10.13"
#include <my_global.h>
#include <my_sys.h>
@@ -50,6 +50,7 @@
#include "mysql.h"
#include "mysql_version.h"
#include "mysqld_error.h"
+#include "../sql/ha_ndbcluster_tables.h"
/* Exit codes */
@@ -95,10 +96,13 @@ 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, opt_notspcs= 0;
+static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*mysql=0;
-static my_bool insert_pat_inited= 0, info_flag;
static DYNAMIC_STRING insert_pat;
static char *opt_password=0,*current_user=0,
*current_host=0,*path=0,*fields_terminated=0,
@@ -114,8 +118,9 @@ 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
-static uint opt_mysql_port= 0, opt_master_data;
-static my_string opt_mysql_unix_port=0;
+static uint opt_mysql_port= 0, opt_master_data;
+static uint my_end_arg;
+static char * opt_mysql_unix_port=0;
static int first_error=0;
static DYNAMIC_STRING extended_row;
#include <sslopt-vars.h>
@@ -151,7 +156,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",
@@ -176,95 +180,110 @@ HASH ignore_table;
static struct my_option my_long_options[] =
{
{"all", 'a', "Deprecated. Use --create-options instead.",
- (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
+ (uchar**) &create_options, (uchar**) &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.",
- (gptr*) &opt_alldbs, (gptr*) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ (uchar**) &opt_alldbs, (uchar**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ 0, 0},
+ {"all-tablespaces", 'Y',
+ "Dump all the tablespaces.",
+ (uchar**) &opt_alltspcs, (uchar**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ 0, 0},
+ {"no-tablespaces", 'y',
+ "Do not dump any tablespace information.",
+ (uchar**) &opt_notspcs, (uchar**) &opt_notspcs, 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,
+ (uchar**) &opt_drop_database, (uchar**) &opt_drop_database, 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, 1, 0, 0, 0, 0,
+ (uchar**) &opt_drop, (uchar**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 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, 1, 0, 0, 0, 0,
+ (uchar**) &opt_lock, (uchar**) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 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},
+ "Allow creation of column names that are keywords.", (uchar**) &opt_keywords,
+ (uchar**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef __NETWARE__
{"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"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},
+ "Directory where character sets are.", (uchar**) &charsets_dir,
+ (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"comments", 'i', "Write additional information.",
- (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
+ (uchar**) &opt_comments, (uchar**) &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.",
- (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0,
+ (uchar**) &opt_compatible_mode_str, (uchar**) &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 --no-set-names --skip-disable-keys --skip-add-locks",
- (gptr*) &opt_compact, (gptr*) &opt_compact, 0, GET_BOOL, NO_ARG, 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",
+ (uchar**) &opt_compact, (uchar**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"complete-insert", 'c', "Use complete insert statements.",
- (gptr*) &opt_complete_insert, (gptr*) &opt_complete_insert, 0, GET_BOOL,
+ (uchar**) &opt_complete_insert, (uchar**) &opt_complete_insert, 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,
+ (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
{"create-options", OPT_CREATE_OPTIONS,
"Include all MySQL specific create options.",
- (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
+ (uchar**) &create_options, (uchar**) &create_options, 0, GET_BOOL, NO_ARG, 1,
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,
+ (uchar**) &opt_databases, (uchar**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
#ifdef DBUG_OFF
{"debug", '#', "This is a non-debug version. Catch this and exit",
0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
#else
- {"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
- (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug", '#', "Output debug log", (uchar**) &default_dbug_option,
+ (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", (gptr*) &info_flag,
- (gptr*) &info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
+ (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
+ (uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
+ 0, GET_BOOL, NO_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},
+ "Set the default character set.", (uchar**) &default_charset,
+ (uchar**) &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,
+ (uchar**) &opt_delayed, (uchar**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"delete-master-logs", OPT_DELETE_MASTER_LOGS,
"Delete logs on master after backup. This automatically enables --master-data.",
- (gptr*) &opt_delete_master_logs, (gptr*) &opt_delete_master_logs, 0,
+ (uchar**) &opt_delete_master_logs, (uchar**) &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.", (gptr*) &opt_disable_keys,
- (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (uchar**) &opt_disable_keys,
+ (uchar**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"events", 'E', "Dump events.",
+ (uchar**) &opt_events, (uchar**) &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,
+ (uchar**) &extended_insert, (uchar**) &extended_insert, 0, GET_BOOL, NO_ARG,
1, 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 in the textfile are terminated by ...", (uchar**) &fields_terminated,
+ (uchar**) &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 in the importfile are enclosed by ...", (uchar**) &enclosed,
+ (uchar**) &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 in the i.file are opt. enclosed by ...", (uchar**) &opt_enclosed,
+ (uchar**) &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, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (uchar**) &escaped, (uchar**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
- (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
+ (uchar**) &opt_lock_all_tables, (uchar**) &opt_lock_all_tables, 0, GET_BOOL, NO_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 "
@@ -275,44 +294,44 @@ static struct my_option my_long_options[] =
"to the moment all tables are locked. So if you want your dump and "
"the log flush to happen at the same exact moment you should use "
"--lock-all-tables or --master-data with --flush-logs",
- (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ (uchar**) &flush_logs, (uchar**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"flush-privileges", OPT_ESC, "Emit a FLUSH PRIVILEGES statement "
"after dumping the mysql database. This option should be used any "
"time the dump contains the mysql database and any other database "
"that depends on the data in the mysql database for proper restore. ",
- (gptr*) &flush_privileges, (gptr*) &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ (uchar**) &flush_privileges, (uchar**) &flush_privileges, 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,
+ (uchar**) &ignore_errors, (uchar**) &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},
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
"VARBINARY, BLOB) in hexadecimal format.",
- (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"host", 'h', "Connect to host.", (gptr*) &current_host,
- (gptr*) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (uchar**) &opt_hex_blob, (uchar**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"host", 'h', "Connect to host.", (uchar**) &current_host,
+ (uchar**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"ignore-table", OPT_IGNORE_TABLE,
"Do not dump the specified table. To specify more than one table to ignore, "
"use the directive multiple times, once for each table. Each table must "
"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},
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
- (gptr*) &opt_ignore, (gptr*) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ (uchar**) &opt_ignore, (uchar**) &opt_ignore, 0, GET_BOOL, NO_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,
+ (uchar**) &lines_terminated, (uchar**) &lines_terminated, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"lock-all-tables", 'x', "Locks all tables across all databases. This "
"is achieved by taking a global read lock for the duration of the whole "
"dump. Automatically turns --single-transaction and --lock-tables off.",
- (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
+ (uchar**) &opt_lock_all_tables, (uchar**) &opt_lock_all_tables, 0, GET_BOOL, NO_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, 1, 0, 0, 0, 0, 0},
+ {"lock-tables", 'l', "Lock all tables for read.", (uchar**) &lock_tables,
+ (uchar**) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.",
- (gptr*) &log_error_file, (gptr*) &log_error_file, 0, GET_STR,
+ (uchar**) &log_error_file, (uchar**) &log_error_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"master-data", OPT_MASTER_DATA,
"This causes the binary log position and filename to be appended to the "
@@ -324,29 +343,29 @@ static struct my_option my_long_options[] =
"- 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.",
- (gptr*) &opt_master_data, (gptr*) &opt_master_data, 0,
+ (uchar**) &opt_master_data, (uchar**) &opt_master_data, 0,
GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
- (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0,
+ (uchar**) &opt_max_allowed_packet, (uchar**) &opt_max_allowed_packet, 0,
GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
(longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
{"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
- (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0,
+ (uchar**) &opt_net_buffer_length, (uchar**) &opt_net_buffer_length, 0,
GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
MALLOC_OVERHEAD-1024, 1024, 0},
{"no-autocommit", OPT_AUTOCOMMIT,
"Wrap tables with autocommit/commit statements.",
- (gptr*) &opt_autocommit, (gptr*) &opt_autocommit, 0, GET_BOOL, NO_ARG,
+ (uchar**) &opt_autocommit, (uchar**) &opt_autocommit, 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,
+ (uchar**) &opt_create_db, (uchar**) &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*) &opt_no_create_info, (gptr*) &opt_no_create_info, 0, GET_BOOL,
+ (uchar**) &opt_no_create_info, (uchar**) &opt_no_create_info, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
- {"no-data", 'd', "No row information.", (gptr*) &opt_no_data,
- (gptr*) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"no-data", 'd', "No row information.", (uchar**) &opt_no_data,
+ (uchar**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"no-set-names", 'N',
"Deprecated. Use --skip-set-charset instead.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -355,7 +374,7 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"order-by-primary", OPT_ORDER_BY_PRIMARY,
"Sorts each table's rows by primary key, or first unique key, if such a key exists. Useful when dumping a MyISAM table to be loaded into an InnoDB table, but will make the dump itself take considerably longer.",
- (gptr*) &opt_order_by_primary, (gptr*) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ (uchar**) &opt_order_by_primary, (uchar**) &opt_order_by_primary, 0, GET_BOOL, 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},
@@ -363,38 +382,35 @@ static struct my_option my_long_options[] =
{"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", 'P', "Port number to use for connection or 0 for default to, in "
- "order of preference, my.cnf, $MYSQL_TCP_PORT, "
-#if MYSQL_PORT_DEFAULT == 0
- "/etc/services, "
-#endif
- "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
- (gptr*) &opt_mysql_port,
- (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
+ {"port", 'P', "Port number to use for connection.", (uchar**) &opt_mysql_port,
+ (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
0},
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"quick", 'q', "Don't buffer query, dump directly to stdout.",
- (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ (uchar**) &quick, (uchar**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"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,
+ (uchar**) &opt_quoted, (uchar**) &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.",
+ (uchar**) &opt_replace_into, (uchar**) &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},
{"routines", 'R', "Dump stored routines (functions and procedures).",
- (gptr*) &opt_routines, (gptr*) &opt_routines, 0, GET_BOOL,
+ (uchar**) &opt_routines, (uchar**) &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.",
- (gptr*) &opt_set_charset, (gptr*) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
+ (uchar**) &opt_set_charset, (uchar**) &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.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
/*
@@ -412,40 +428,40 @@ static struct my_option my_long_options[] =
"connection should use the following statements: ALTER TABLE, DROP "
"TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
"isolated from them. Option automatically turns off --lock-tables.",
- (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0,
+ (uchar**) &opt_single_transaction, (uchar**) &opt_single_transaction, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
- (gptr*) &opt_dump_date, (gptr*) &opt_dump_date, 0,
+ (uchar**) &opt_dump_date, (uchar**) &opt_dump_date, 0,
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"skip-opt", OPT_SKIP_OPTIMIZATION,
"Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
0, 0, 0, GET_NO_ARG, NO_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,
+ (uchar**) &opt_mysql_unix_port, (uchar**) &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},
+ (uchar**) &path, (uchar**) &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},
{"triggers", OPT_TRIGGERS, "Dump triggers for each dumped table",
- (gptr*) &opt_dump_triggers, (gptr*) &opt_dump_triggers, 0, GET_BOOL,
+ (uchar**) &opt_dump_triggers, (uchar**) &opt_dump_triggers, 0, GET_BOOL,
NO_ARG, 1, 0, 0, 0, 0, 0},
{"tz-utc", OPT_TZ_UTC,
"SET TIME_ZONE='+00:00' at top of dump to allow dumping of TIMESTAMP data when a server has data in different time zones or data is being moved between servers with different time zones.",
- (gptr*) &opt_tz_utc, (gptr*) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ (uchar**) &opt_tz_utc, (uchar**) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
#ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user.",
- (gptr*) &current_user, (gptr*) &current_user, 0, GET_STR, REQUIRED_ARG,
+ (uchar**) &current_user, (uchar**) &current_user, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
#endif
{"verbose", 'v', "Print info about the various stages.",
- (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ (uchar**) &verbose, (uchar**) &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},
+ (uchar**) &where, (uchar**) &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},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
@@ -472,6 +488,10 @@ char check_if_ignore_table(const char *table_name, char *table_type);
static char *primary_key_fields(const char *table_name);
static my_bool get_view_structure(char *table, char* db);
static my_bool dump_all_views_in_db(char *database);
+static int dump_all_tablespaces();
+static int dump_tablespaces_for_tables(char *db, char **table_names, int tables);
+static int dump_tablespaces_for_databases(char** databases);
+static int dump_tablespaces(char* ts_where);
#include <help_start.h>
@@ -558,8 +578,10 @@ static void write_header(FILE *sql_file, char *db_name)
if (opt_xml)
{
fputs("<?xml version=\"1.0\"?>\n", sql_file);
- /* Schema reference. Allows use of xsi:nil for NULL values and
- xsi:type to define an element's data type. */
+ /*
+ Schema reference. Allows use of xsi:nil for NULL values and
+ xsi:type to define an element's data type.
+ */
fputs("<mysqldump ", sql_file);
fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
sql_file);
@@ -570,7 +592,9 @@ static void write_header(FILE *sql_file, char *db_name)
{
if (opt_comments)
{
- fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
+ fprintf(sql_file,
+ "-- MySQL dump %s Distrib %s, for %s (%s)\n--\n",
+ DUMP_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
fprintf(sql_file, "-- Host: %s Database: %s\n",
current_host ? current_host : "localhost", db_name ? db_name :
"");
@@ -652,18 +676,18 @@ static void write_footer(FILE *sql_file)
}
} /* write_footer */
-static void free_table_ent(char *key)
+static void free_table_ent(char *key)
{
- my_free((gptr) key, MYF(0));
+ my_free(key, MYF(0));
}
-byte* get_table_key(const char *entry, uint *length,
- my_bool not_used __attribute__((unused)))
+uchar* get_table_key(const char *entry, size_t *length,
+ my_bool not_used __attribute__((unused)))
{
- *length= (uint) strlen(entry);
- return (byte*) entry;
+ *length= strlen(entry);
+ return (uchar*) entry;
}
@@ -678,6 +702,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
#endif
case 'p':
+ if (argument == disabled_my_option)
+ argument= (char*) ""; /* Don't require password */
if (argument)
{
char *start=argument;
@@ -721,7 +747,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case '#':
DBUG_PUSH(argument ? argument : default_dbug_option);
- info_flag= 1;
+ debug_check_flag= 1;
break;
#include <sslopt-case.h>
case 'V': print_version(); exit(0);
@@ -762,7 +788,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n");
exit(1);
}
- if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0))))
+ if (my_hash_insert(&ignore_table, (uchar*)my_strdup(argument, MYF(0))))
exit(EX_EOM);
break;
}
@@ -791,7 +817,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
uint size_for_sql_mode= 0;
const char **ptr;
for (ptr= compatible_mode_names; *ptr; ptr++)
- size_for_sql_mode+= (uint) strlen(*ptr);
+ size_for_sql_mode+= strlen(*ptr);
size_for_sql_mode+= sizeof(compatible_mode_names)-1;
DBUG_ASSERT(sizeof(compatible_mode_normal_str)>=size_for_sql_mode);
}
@@ -816,14 +842,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
}
case (int) OPT_MYSQL_PROTOCOL:
- {
- if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0)
- {
- fprintf(stderr, "Unknown option to protocol: %s\n", argument);
- exit(1);
- }
- break;
- }
+ opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
+ opt->name);
+ break;
}
return 0;
}
@@ -844,11 +865,15 @@ static int get_options(int *argc, char ***argv)
(hash_get_key) get_table_key,
(hash_free_key) free_table_ent, 0))
return(EX_EOM);
- /* Don't copy cluster internal log tables */
+ /* Don't copy internal log tables */
if (my_hash_insert(&ignore_table,
- (byte*) my_strdup("mysql.apply_status", MYF(MY_WME))) ||
+ (uchar*) my_strdup("mysql.apply_status", MYF(MY_WME))) ||
+ my_hash_insert(&ignore_table,
+ (uchar*) my_strdup("mysql.schema", MYF(MY_WME))) ||
+ my_hash_insert(&ignore_table,
+ (uchar*) my_strdup("mysql.general_log", MYF(MY_WME))) ||
my_hash_insert(&ignore_table,
- (byte*) my_strdup("mysql.schema", MYF(MY_WME))))
+ (uchar*) my_strdup("mysql.slow_log", MYF(MY_WME))))
return(EX_EOM);
if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
@@ -856,6 +881,10 @@ static int get_options(int *argc, char ***argv)
*mysql_params->p_max_allowed_packet= opt_max_allowed_packet;
*mysql_params->p_net_buffer_length= opt_net_buffer_length;
+ if (debug_info_flag)
+ my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
+ if (debug_check_flag)
+ my_end_arg= MY_CHECK_ERROR;
if (opt_delayed)
opt_lock=0; /* Can't have lock with delayed */
@@ -1013,6 +1042,207 @@ static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res,
}
+static int fetch_db_collation(const char *db_name,
+ char *db_cl_name,
+ int db_cl_size)
+{
+ my_bool err_status= FALSE;
+ char query[QUERY_LENGTH];
+ MYSQL_RES *db_cl_res;
+ MYSQL_ROW db_cl_row;
+ char quoted_database_buf[NAME_LEN*2+3];
+ char *qdatabase= quote_name(db_name, quoted_database_buf, 1);
+
+ my_snprintf(query, sizeof (query), "use %s", qdatabase);
+
+ if (mysql_query_with_error_report(mysql, NULL, query))
+ return 1;
+
+ if (mysql_query_with_error_report(mysql, &db_cl_res,
+ "select @@collation_database"))
+ return 1;
+
+ do
+ {
+ if (mysql_num_rows(db_cl_res) != 1)
+ {
+ err_status= TRUE;
+ break;
+ }
+
+ if (!(db_cl_row= mysql_fetch_row(db_cl_res)))
+ {
+ err_status= TRUE;
+ break;
+ }
+
+ strncpy(db_cl_name, db_cl_row[0], db_cl_size);
+ db_cl_name[db_cl_size - 1]= 0; /* just in case. */
+
+ } while (FALSE);
+
+ mysql_free_result(db_cl_res);
+
+ return err_status ? 1 : 0;
+}
+
+
+static char *my_case_str(const char *str,
+ uint str_len,
+ const char *token,
+ uint token_len)
+{
+ my_match_t match;
+
+ uint status= my_charset_latin1.coll->instr(&my_charset_latin1,
+ str, str_len,
+ token, token_len,
+ &match, 1);
+
+ return status ? (char *) str + match.end : NULL;
+}
+
+
+static int switch_db_collation(FILE *sql_file,
+ const char *db_name,
+ const char *delimiter,
+ const char *current_db_cl_name,
+ const char *required_db_cl_name,
+ int *db_cl_altered)
+{
+ if (strcmp(current_db_cl_name, required_db_cl_name) != 0)
+ {
+ CHARSET_INFO *db_cl= get_charset_by_name(required_db_cl_name, MYF(0));
+
+ if (!db_cl)
+ return 1;
+
+ fprintf(sql_file,
+ "ALTER DATABASE %s CHARACTER SET %s COLLATE %s %s\n",
+ (const char *) db_name,
+ (const char *) db_cl->csname,
+ (const char *) db_cl->name,
+ (const char *) delimiter);
+
+ *db_cl_altered= 1;
+
+ return 0;
+ }
+
+ *db_cl_altered= 0;
+
+ return 0;
+}
+
+
+static int restore_db_collation(FILE *sql_file,
+ const char *db_name,
+ const char *delimiter,
+ const char *db_cl_name)
+{
+ CHARSET_INFO *db_cl= get_charset_by_name(db_cl_name, MYF(0));
+
+ if (!db_cl)
+ return 1;
+
+ fprintf(sql_file,
+ "ALTER DATABASE %s CHARACTER SET %s COLLATE %s %s\n",
+ (const char *) db_name,
+ (const char *) db_cl->csname,
+ (const char *) db_cl->name,
+ (const char *) delimiter);
+
+ return 0;
+}
+
+
+static void switch_cs_variables(FILE *sql_file,
+ const char *delimiter,
+ const char *character_set_client,
+ const char *character_set_results,
+ const char *collation_connection)
+{
+ fprintf(sql_file,
+ "/*!50003 SET @saved_cs_client = @@character_set_client */ %s\n"
+ "/*!50003 SET @saved_cs_results = @@character_set_results */ %s\n"
+ "/*!50003 SET @saved_col_connection = @@collation_connection */ %s\n"
+ "/*!50003 SET character_set_client = %s */ %s\n"
+ "/*!50003 SET character_set_results = %s */ %s\n"
+ "/*!50003 SET collation_connection = %s */ %s\n",
+ (const char *) delimiter,
+ (const char *) delimiter,
+ (const char *) delimiter,
+
+ (const char *) character_set_client,
+ (const char *) delimiter,
+
+ (const char *) character_set_results,
+ (const char *) delimiter,
+
+ (const char *) collation_connection,
+ (const char *) delimiter);
+}
+
+
+static void restore_cs_variables(FILE *sql_file,
+ const char *delimiter)
+{
+ fprintf(sql_file,
+ "/*!50003 SET character_set_client = @saved_cs_client */ %s\n"
+ "/*!50003 SET character_set_results = @saved_cs_results */ %s\n"
+ "/*!50003 SET collation_connection = @saved_col_connection */ %s\n",
+ (const char *) delimiter,
+ (const char *) delimiter,
+ (const char *) delimiter);
+}
+
+
+static void switch_sql_mode(FILE *sql_file,
+ const char *delimiter,
+ const char *sql_mode)
+{
+ fprintf(sql_file,
+ "/*!50003 SET @saved_sql_mode = @@sql_mode */ %s\n"
+ "/*!50003 SET sql_mode = '%s' */ %s\n",
+ (const char *) delimiter,
+
+ (const char *) sql_mode,
+ (const char *) delimiter);
+}
+
+
+static void restore_sql_mode(FILE *sql_file,
+ const char *delimiter)
+{
+ fprintf(sql_file,
+ "/*!50003 SET sql_mode = @saved_sql_mode */ %s\n",
+ (const char *) delimiter);
+}
+
+
+static void switch_time_zone(FILE *sql_file,
+ const char *delimiter,
+ const char *time_zone)
+{
+ fprintf(sql_file,
+ "/*!50003 SET @saved_time_zone = @@time_zone */ %s\n"
+ "/*!50003 SET time_zone = '%s' */ %s\n",
+ (const char *) delimiter,
+
+ (const char *) time_zone,
+ (const char *) delimiter);
+}
+
+
+static void restore_time_zone(FILE *sql_file,
+ const char *delimiter)
+{
+ fprintf(sql_file,
+ "/*!50003 SET time_zone = @saved_time_zone */ %s\n",
+ (const char *) delimiter);
+}
+
+
/**
Switch charset for results to some specified charset. If the server does not
support character_set_results variable, nothing can be done here. As for
@@ -1039,9 +1269,127 @@ static int switch_character_set_results(MYSQL *mysql, const char *cs_name)
"SET SESSION character_set_results = '%s'",
(const char *) cs_name);
- return mysql_real_query(mysql, query_buffer, (uint) query_length);
+ return mysql_real_query(mysql, query_buffer, query_length);
+}
+
+/**
+ 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.
+
+ This function parses the CREATE FUNCTION | PROCEDURE 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.
+
+ @return pointer to the new allocated query string.
+*/
+
+static char *cover_definer_clause_in_sp(const char *def_str,
+ uint def_str_length)
+{
+ char *query_str= NULL;
+ char *definer_begin= my_case_str(def_str, def_str_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(" PROCEDURE"));
+
+ if (!definer_end)
+ {
+ definer_end= my_case_str(definer_begin, strlen(definer_begin),
+ C_STRING_WITH_LEN(" FUNCTION"));
+ }
+
+ 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(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);
+ }
+
+ return query_str;
+}
/*
Open a new .sql file to dump the table or view into
@@ -1049,18 +1397,19 @@ static int switch_character_set_results(MYSQL *mysql, const char *cs_name)
SYNOPSIS
open_sql_file_for_table
name name of the table or view
+ flags flags (as per "man 2 open")
RETURN VALUES
0 Failed to open file
> 0 Handle of the open file
*/
-static FILE* open_sql_file_for_table(const char* table)
+static FILE* open_sql_file_for_table(const char* table, int flags)
{
FILE* res;
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
convert_dirname(tmp_path,path,NullS);
res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
- O_WRONLY, MYF(MY_WME));
+ flags, MYF(MY_WME));
return res;
}
@@ -1078,7 +1427,7 @@ static void free_resources()
dynstr_free(&insert_pat);
if (defaults_argv)
free_defaults(defaults_argv);
- my_end(info_flag ? MY_CHECK_ERROR : 0);
+ my_end(my_end_arg);
}
@@ -1372,8 +1721,7 @@ static void print_xml_tag(FILE * xml_file, const char* sbeg,
fputs(attribute_name, xml_file);
fputc('\"', xml_file);
- print_quoted_xml(xml_file, attribute_value,
- (uint) strlen(attribute_value));
+ print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
fputc('\"', xml_file);
attribute_name= va_arg(arg_list, char *);
@@ -1413,7 +1761,7 @@ static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
fputs("<", xml_file);
fputs(stag_atr, xml_file);
fputs("\"", xml_file);
- print_quoted_xml(xml_file, sval, (uint) strlen(sval));
+ print_quoted_xml(xml_file, sval, strlen(sval));
fputs("\" xsi:nil=\"true\" />", xml_file);
fputs(line_end, xml_file);
check_io(xml_file);
@@ -1463,6 +1811,203 @@ 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];
+ FILE *sql_file= md_result_file;
+ MYSQL_RES *event_res, *event_list_res;
+ MYSQL_ROW row, event_list_row;
+
+ char db_cl_name[MY_CS_NAME_SIZE];
+ int db_cl_altered= FALSE;
+
+ DBUG_ENTER("dump_events_for_db");
+ DBUG_PRINT("enter", ("db: '%s'", db));
+
+ mysql_real_escape_string(mysql, db_name_buff, db, strlen(db));
+
+ /* nice comments */
+ if (opt_comments)
+ fprintf(sql_file, "\n--\n-- Dumping events for database '%s'\n--\n", db);
+
+ /*
+ not using "mysql_query_with_error_report" because we may have not
+ enough privileges to lock mysql.events.
+ */
+ if (lock_tables)
+ mysql_query(mysql, "LOCK TABLES mysql.event READ");
+
+ if (mysql_query_with_error_report(mysql, &event_list_res, "show events"))
+ DBUG_RETURN(0);
+
+ strcpy(delimiter, ";");
+ if (mysql_num_rows(event_list_res) > 0)
+ {
+ fprintf(sql_file, "/*!50106 SET @save_time_zone= @@TIME_ZONE */ ;\n");
+
+ /* Get database collation. */
+
+ if (fetch_db_collation(db_name_buff, db_cl_name, sizeof (db_cl_name)))
+ DBUG_RETURN(1);
+
+ if (switch_character_set_results(mysql, "binary"))
+ DBUG_RETURN(1);
+
+ 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(mysql, &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[3]) != 0)
+ {
+ if (opt_drop)
+ fprintf(sql_file, "/*!50106 DROP EVENT IF EXISTS %s */%s\n",
+ event_name, delimiter);
+
+ 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);
+ DBUG_RETURN(1);
+ }
+
+ fprintf(sql_file, "DELIMITER %s\n", delimiter);
+
+ if (mysql_num_fields(event_res) >= 7)
+ {
+ if (switch_db_collation(sql_file, db_name_buff, delimiter,
+ db_cl_name, row[6], &db_cl_altered))
+ {
+ DBUG_RETURN(1);
+ }
+
+ switch_cs_variables(sql_file, delimiter,
+ row[4], /* character_set_client */
+ 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.
+
+ 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");
+ }
+
+ switch_sql_mode(sql_file, delimiter, row[1]);
+
+ switch_time_zone(sql_file, delimiter, row[2]);
+
+ fprintf(sql_file,
+ "/*!50106 %s */ %s\n",
+ (const char *) row[3],
+ (const char *) delimiter);
+
+ restore_time_zone(sql_file, delimiter);
+ restore_sql_mode(sql_file, delimiter);
+
+ if (mysql_num_fields(event_res) >= 7)
+ {
+ restore_cs_variables(sql_file, delimiter);
+
+ if (db_cl_altered)
+ {
+ if (restore_db_collation(sql_file, db_name_buff, delimiter,
+ db_cl_name))
+ DBUG_RETURN(1);
+ }
+ }
+ }
+ } /* end of event printing */
+ mysql_free_result(event_res);
+
+ } /* end of list of events */
+ fprintf(sql_file, "DELIMITER ;\n");
+ fprintf(sql_file, "/*!50106 SET TIME_ZONE= @save_time_zone */ ;\n");
+
+ if (switch_character_set_results(mysql, default_charset))
+ DBUG_RETURN(1);
+ }
+ mysql_free_result(event_list_res);
+
+ if (lock_tables)
+ VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
+ DBUG_RETURN(0);
+}
+
+
/*
Print hex value for blob data.
@@ -1500,7 +2045,7 @@ static void print_blob_as_hex(FILE *output_file, const char *str, ulong len)
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;
@@ -1508,10 +2053,14 @@ static uint dump_routines_for_db(char *db)
FILE *sql_file= md_result_file;
MYSQL_RES *routine_res, *routine_list_res;
MYSQL_ROW row, routine_list_row;
+
+ char db_cl_name[MY_CS_NAME_SIZE];
+ int db_cl_altered= FALSE;
+
DBUG_ENTER("dump_routines_for_db");
DBUG_PRINT("enter", ("db: '%s'", db));
- mysql_real_escape_string(mysql, db_name_buff, db, (uint) strlen(db));
+ mysql_real_escape_string(mysql, db_name_buff, db, strlen(db));
/* nice comments */
if (opt_comments)
@@ -1524,10 +2073,13 @@ static uint dump_routines_for_db(char *db)
if (lock_tables)
mysql_query(mysql, "LOCK TABLES mysql.proc READ");
- if (opt_compact)
- fprintf(sql_file, "\n/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n");
+ /* Get database collation. */
- fprintf(sql_file, "DELIMITER ;;\n");
+ if (fetch_db_collation(db_name_buff, db_cl_name, sizeof (db_cl_name)))
+ DBUG_RETURN(1);
+
+ if (switch_character_set_results(mysql, "binary"))
+ DBUG_RETURN(1);
/* 0, retrieve and dump functions, 1, procedures */
for (i= 0; i <= 1; i++)
@@ -1544,9 +2096,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);
@@ -1570,63 +2122,67 @@ static uint dump_routines_for_db(char *db)
}
else if (strlen(row[2]))
{
- char *query_str= NULL;
- char *definer_begin;
-
+ char *query_str;
if (opt_drop)
- fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n",
+ fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n",
routine_type[i], routine_name);
- /*
- Cover DEFINER-clause in version-specific comments.
-
- TODO: this is definitely a BAD IDEA to parse SHOW CREATE output.
- We should user INFORMATION_SCHEMA instead. The only problem is
- that now INFORMATION_SCHEMA does not provide information about
- routine parameters.
- */
+ query_str= cover_definer_clause_in_sp(row[2], strlen(row[2]));
- definer_begin= strstr(row[2], " DEFINER");
+ if (mysql_num_fields(routine_res) >= 6)
+ {
+ if (switch_db_collation(sql_file, db_name_buff, ";",
+ db_cl_name, row[5], &db_cl_altered))
+ {
+ DBUG_RETURN(1);
+ }
- if (definer_begin)
+ switch_cs_variables(sql_file, ";",
+ row[3], /* character_set_client */
+ row[3], /* character_set_results */
+ row[4]); /* collation_connection */
+ }
+ else
{
- char *definer_end= strstr(definer_begin, " PROCEDURE");
+ /*
+ 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 stored
+ procedure/function properly.
+ */
+
+ fprintf(sql_file,
+ "--\n"
+ "-- WARNING: old server version. "
+ "The following dump may be incomplete.\n"
+ "--\n");
+ }
- if (!definer_end)
- definer_end= strstr(definer_begin, " FUNCTION");
- if (definer_end)
- {
- char *query_str_tail;
+ switch_sql_mode(sql_file, ";", row[1]);
- /*
- Allocate memory for new query string: original string
- from SHOW statement and version-specific comments.
- */
- query_str= alloc_query_str((uint) strlen(row[2]) + 23);
-
- query_str_tail= strnmov(query_str, row[2],
- (uint) (definer_begin - row[2]));
- query_str_tail= strmov(query_str_tail, "*/ /*!50020");
- query_str_tail= strnmov(query_str_tail, definer_begin,
- (uint) (definer_end - definer_begin));
- query_str_tail= strxmov(query_str_tail, "*/ /*!50003",
- definer_end, NullS);
+ fprintf(sql_file,
+ "DELIMITER ;;\n"
+ "/*!50003 %s */;;\n"
+ "DELIMITER ;\n",
+ (const char *) (query_str != NULL ? query_str : row[2]));
+
+ restore_sql_mode(sql_file, ";");
+
+ if (mysql_num_fields(routine_res) >= 6)
+ {
+ restore_cs_variables(sql_file, ";");
+
+ if (db_cl_altered)
+ {
+ if (restore_db_collation(sql_file, db_name_buff, ";", db_cl_name))
+ DBUG_RETURN(1);
}
}
- /*
- we need to change sql_mode only for the CREATE
- PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name
- */
- fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n",
- row[1] /* sql_mode */);
- fprintf(sql_file, "/*!50003 %s */;;\n",
- (query_str != NULL ? query_str : row[2]));
- fprintf(sql_file,
- "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/"
- ";;\n");
-
my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
}
} /* end of routine printing */
@@ -1636,8 +2192,9 @@ static uint dump_routines_for_db(char *db)
}
mysql_free_result(routine_list_res);
} /* end of for i (0 .. 1) */
- /* set the delimiter back to ';' */
- fprintf(sql_file, "DELIMITER ;\n");
+
+ if (switch_character_set_results(mysql, default_charset))
+ DBUG_RETURN(1);
if (lock_tables)
VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
@@ -1666,13 +2223,12 @@ 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;
MYSQL_ROW row;
-
DBUG_ENTER("get_table_structure");
DBUG_PRINT("enter", ("db: %s table: %s", db, table));
@@ -1735,7 +2291,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (path)
{
- if (!(sql_file= open_sql_file_for_table(table)))
+ if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
DBUG_RETURN(0);
write_header(sql_file, db);
@@ -1787,7 +2343,9 @@ static uint get_table_structure(char *table, char *db, char *table_type,
*/
my_snprintf(query_buff, sizeof(query_buff),
"SHOW FIELDS FROM %s", result_table);
- if (mysql_query_with_error_report(mysql, 0, query_buff))
+ if (switch_character_set_results(mysql, "binary") ||
+ mysql_query_with_error_report(mysql, &result, query_buff) ||
+ switch_character_set_results(mysql, default_charset))
{
/*
View references invalid or privileged table/col/fun (err 1356),
@@ -1805,49 +2363,57 @@ static uint get_table_structure(char *table, char *db, char *table_type,
else
my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
- if ((result= mysql_store_result(mysql)))
+ if (mysql_num_rows(result))
{
- if (mysql_num_rows(result))
+ if (opt_drop)
{
- if (opt_drop)
- {
/*
- We have already dropped any table of the same name
- above, so here we just drop the view.
- */
+ We have already dropped any table of the same name above, so
+ here we just drop the view.
+ */
- fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
- opt_quoted_table);
- check_io(sql_file);
- }
+ fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
+ opt_quoted_table);
+ check_io(sql_file);
+ }
- fprintf(sql_file, "/*!50001 CREATE TABLE %s (\n", result_table);
- /*
- Get first row, following loop will prepend comma - keeps
- from having to know if the row being printed is last to
- determine if there should be a _trailing_ comma.
- */
- row= mysql_fetch_row(result);
+ fprintf(sql_file,
+ "SET @saved_cs_client = @@character_set_client;\n"
+ "SET character_set_client = utf8;\n"
+ "/*!50001 CREATE TABLE %s (\n",
+ result_table);
- fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0),
- row[1]);
+ /*
+ Get first row, following loop will prepend comma - keeps from
+ having to know if the row being printed is last to determine if
+ there should be a _trailing_ comma.
+ */
- 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]);
- }
- /*
- Stand-in tables are always MyISAM tables as the default
- engine might have a column-limit that's lower than the
- number of columns in the view, and MyISAM support is
- guaranteed to be in the server anyway.
- */
- fprintf(sql_file, "\n) ENGINE=MyISAM */;\n");
- check_io(sql_file);
+ row= mysql_fetch_row(result);
+
+ fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0),
+ row[1]);
+
+ 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]);
}
+
+ /*
+ Stand-in tables are always MyISAM tables as the default
+ engine might have a column-limit that's lower than the
+ number of columns in the view, and MyISAM support is
+ guaranteed to be in the server anyway.
+ */
+ fprintf(sql_file,
+ "\n) ENGINE=MyISAM */;\n"
+ "SET character_set_client = @saved_cs_client;\n");
+
+ check_io(sql_file);
}
+
mysql_free_result(result);
if (path)
@@ -1886,7 +2452,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
*/
if (write_data)
{
- dynstr_append_checked(&insert_pat, "INSERT ");
+ if (opt_replace_into)
+ dynstr_append_checked(&insert_pat, "REPLACE ");
+ else
+ dynstr_append_checked(&insert_pat, "INSERT ");
dynstr_append_checked(&insert_pat, insert_option);
dynstr_append_checked(&insert_pat, "INTO ");
dynstr_append_checked(&insert_pat, opt_quoted_table);
@@ -1933,7 +2502,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
if (path)
{
- if (!(sql_file= open_sql_file_for_table(table)))
+ if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
DBUG_RETURN(0);
write_header(sql_file, db);
}
@@ -1952,7 +2521,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (write_data)
{
- dynstr_append_checked(&insert_pat, "INSERT ");
+ if (opt_replace_into)
+ dynstr_append_checked(&insert_pat, "REPLACE ");
+ else
+ dynstr_append_checked(&insert_pat, "INSERT ");
dynstr_append_checked(&insert_pat, insert_option);
dynstr_append_checked(&insert_pat, "INTO ");
dynstr_append_checked(&insert_pat, result_table);
@@ -2083,6 +2655,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
fprintf(sql_file, " (%s)",row[7]); /* Sub key */
check_io(sql_file);
}
+ mysql_free_result(result);
if (!opt_xml)
{
if (keynr)
@@ -2153,102 +2726,226 @@ continue_xml:
DBUG_RETURN((uint) num_fields);
} /* get_table_structure */
+static void dump_trigger_old(FILE *sql_file, MYSQL_RES *show_triggers_rs,
+ MYSQL_ROW *show_trigger_row,
+ const char *table_name)
+{
+ char quoted_table_name_buf[NAME_LEN * 2 + 3];
+ char *quoted_table_name= quote_name(table_name, quoted_table_name_buf, 1);
+
+ char name_buff[NAME_LEN * 4 + 3];
+
+ DBUG_ENTER("dump_trigger_old");
+
+ fprintf(sql_file,
+ "--\n"
+ "-- WARNING: old server version. "
+ "The following dump may be incomplete.\n"
+ "--\n");
+
+ if (opt_compact)
+ fprintf(sql_file, "/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n");
+
+ fprintf(sql_file,
+ "DELIMITER ;;\n"
+ "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n"
+ "/*!50003 CREATE */ ",
+ (*show_trigger_row)[6]);
+
+ if (mysql_num_fields(show_triggers_rs) > 7)
+ {
+ /*
+ mysqldump can be run against the server, that does not support
+ definer in triggers (there is no DEFINER column in SHOW TRIGGERS
+ output). So, we should check if we have this column before
+ accessing it.
+ */
+
+ size_t user_name_len;
+ char user_name_str[USERNAME_LENGTH + 1];
+ char quoted_user_name_str[USERNAME_LENGTH * 2 + 3];
+ size_t host_name_len;
+ char host_name_str[HOSTNAME_LENGTH + 1];
+ char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
+
+ parse_user((*show_trigger_row)[7],
+ strlen((*show_trigger_row)[7]),
+ user_name_str, &user_name_len,
+ host_name_str, &host_name_len);
+
+ fprintf(sql_file,
+ "/*!50017 DEFINER=%s@%s */ ",
+ quote_name(user_name_str, quoted_user_name_str, FALSE),
+ quote_name(host_name_str, quoted_host_name_str, FALSE));
+ }
+
+ fprintf(sql_file,
+ "/*!50003 TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n"
+ "DELIMITER ;\n",
+ quote_name((*show_trigger_row)[0], name_buff, 0), /* Trigger */
+ (*show_trigger_row)[4], /* Timing */
+ (*show_trigger_row)[1], /* Event */
+ quoted_table_name,
+ (strchr(" \t\n\r", *((*show_trigger_row)[3]))) ? "" : " ",
+ (*show_trigger_row)[3] /* Statement */);
+
+ if (opt_compact)
+ fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n");
+
+ DBUG_VOID_RETURN;
+}
+
+static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
+ const char *db_name,
+ const char *db_cl_name)
+{
+ MYSQL_ROW row;
+ int db_cl_altered= FALSE;
+
+ DBUG_ENTER("dump_trigger");
+
+ while ((row= mysql_fetch_row(show_create_trigger_rs)))
+ {
+ char *query_str= cover_definer_clause_in_trigger(row[2], strlen(row[2]));
-/*
- dump_triggers_for_table
+ if (switch_db_collation(sql_file, db_name, ";",
+ db_cl_name, row[5], &db_cl_altered))
+ DBUG_RETURN(TRUE);
- Dumps the triggers given a table/db name. This should be called after
- the tables have been dumped in case a trigger depends on the existence
- of a table
+ switch_cs_variables(sql_file, ";",
+ row[3], /* character_set_client */
+ row[3], /* character_set_results */
+ row[4]); /* collation_connection */
+ switch_sql_mode(sql_file, ";", row[1]);
+
+ fprintf(sql_file,
+ "DELIMITER ;;\n"
+ "/*!50003 %s */;;\n"
+ "DELIMITER ;\n",
+ (const char *) (query_str != NULL ? query_str : row[2]));
+
+ restore_sql_mode(sql_file, ";");
+ restore_cs_variables(sql_file, ";");
+
+ if (db_cl_altered)
+ {
+ if (restore_db_collation(sql_file, db_name, ";", db_cl_name))
+ DBUG_RETURN(TRUE);
+ }
+
+ my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+/**
+ Dump the triggers for a given table.
+
+ This should be called after the tables have been dumped in case a trigger
+ depends on the existence of a table.
+
+ @param[in] table_name
+ @param[in] db_name
+
+ @return Error status.
+ @retval TRUE error has occurred.
+ @retval FALSE operation succeed.
*/
-static void dump_triggers_for_table(char *table,
- char *db __attribute__((unused)))
+static int dump_triggers_for_table(char *table_name, char *db_name)
{
- char *result_table;
- char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
- char query_buff[512];
- uint old_opt_compatible_mode=opt_compatible_mode;
- FILE *sql_file= md_result_file;
- MYSQL_RES *result;
+ char name_buff[NAME_LEN*4+3];
+ char query_buff[QUERY_LENGTH];
+ uint old_opt_compatible_mode= opt_compatible_mode;
+ MYSQL_RES *show_triggers_rs;
MYSQL_ROW row;
+ FILE *sql_file= md_result_file;
+
+ char db_cl_name[MY_CS_NAME_SIZE];
+ int ret= TRUE;
+
DBUG_ENTER("dump_triggers_for_table");
- DBUG_PRINT("enter", ("db: %s, table: %s", db, table));
+ DBUG_PRINT("enter", ("db: %s, table_name: %s", db_name, table_name));
+
+ if (path && !(sql_file= open_sql_file_for_table(table_name,
+ O_WRONLY | O_APPEND)))
+ DBUG_RETURN(1);
/* Do not use ANSI_QUOTES on triggers in dump */
opt_compatible_mode&= ~MASK_ANSI_QUOTES;
- result_table= quote_name(table, table_buff, 1);
+
+ /* Get database collation. */
+
+ if (switch_character_set_results(mysql, "binary"))
+ goto done;
+
+ if (fetch_db_collation(db_name, db_cl_name, sizeof (db_cl_name)))
+ goto done;
+
+ /* Get list of triggers. */
my_snprintf(query_buff, sizeof(query_buff),
"SHOW TRIGGERS LIKE %s",
- quote_for_like(table, name_buff));
+ quote_for_like(table_name, name_buff));
- if (mysql_query_with_error_report(mysql, &result, query_buff))
- {
- if (path)
- my_fclose(sql_file, MYF(MY_WME));
- DBUG_VOID_RETURN;
- }
- if (mysql_num_rows(result))
- {
- fprintf(sql_file, "\n/*!50003 SET @SAVE_SQL_MODE=@@SQL_MODE*/;\n");
- fprintf(sql_file, "\nDELIMITER ;;\n");
- }
- while ((row= mysql_fetch_row(result)))
+ if (mysql_query_with_error_report(mysql, &show_triggers_rs, query_buff))
+ goto done;
+
+ /* Dump triggers. */
+
+ while ((row= mysql_fetch_row(show_triggers_rs)))
{
- fprintf(sql_file,
- "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n"
- "/*!50003 CREATE */ ",
- row[6] /* sql_mode */);
- if (mysql_num_fields(result) > 7)
+ my_snprintf(query_buff, sizeof (query_buff),
+ "SHOW CREATE TRIGGER %s",
+ quote_name(row[0], name_buff, TRUE));
+
+ if (mysql_query(mysql, query_buff))
{
/*
- mysqldump can be run against the server, that does not support definer
- in triggers (there is no DEFINER column in SHOW TRIGGERS output). So,
- we should check if we have this column before accessing it.
+ mysqldump is being run against old server, that does not support
+ SHOW CREATE TRIGGER statement. We should use SHOW TRIGGERS output.
+
+ NOTE: the dump may be incorrect, as old SHOW TRIGGERS does not
+ provide all the necessary information to restore trigger properly.
*/
- uint user_name_len;
- char user_name_str[USERNAME_LENGTH + 1];
- char quoted_user_name_str[USERNAME_LENGTH * 2 + 3];
- uint host_name_len;
- char host_name_str[HOSTNAME_LENGTH + 1];
- char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
+ dump_trigger_old(sql_file, show_triggers_rs, &row, table_name);
+ }
+ else
+ {
+ MYSQL_RES *show_create_trigger_rs= mysql_store_result(mysql);
- parse_user(row[7], (uint) strlen(row[7]), user_name_str, &user_name_len,
- host_name_str, &host_name_len);
+ if (!show_create_trigger_rs ||
+ dump_trigger(sql_file, show_create_trigger_rs, db_name, db_cl_name))
+ goto done;
- fprintf(sql_file,
- "/*!50017 DEFINER=%s@%s */ ",
- quote_name(user_name_str, quoted_user_name_str, FALSE),
- quote_name(host_name_str, quoted_host_name_str, FALSE));
+ mysql_free_result(show_create_trigger_rs);
}
- fprintf(sql_file,
- "/*!50003 TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n\n",
- quote_name(row[0], name_buff, 0), /* Trigger */
- row[4], /* Timing */
- row[1], /* Event */
- result_table,
- (strchr(" \t\n\r", *(row[3]))) ? "" : " ",
- row[3] /* Statement */);
}
- if (mysql_num_rows(result))
- {
- fprintf(sql_file,
- "DELIMITER ;\n"
- "/*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/;\n");
- }
- mysql_free_result(result);
+
+ mysql_free_result(show_triggers_rs);
+
+ if (switch_character_set_results(mysql, default_charset))
+ goto done;
+
/*
make sure to set back opt_compatible mode to
original value
*/
opt_compatible_mode=old_opt_compatible_mode;
- DBUG_VOID_RETURN;
+
+ ret= FALSE;
+
+done:
+ if (path)
+ my_fclose(sql_file, MYF(0));
+
+ DBUG_RETURN(ret);
}
static void add_load_option(DYNAMIC_STRING *str, const char *option,
@@ -2365,7 +3062,7 @@ static void dump_table(char *table, char *db)
/*
The "table" could be a view. If so, we don't do anything here.
*/
- if (strcmp (table_type, "VIEW") == 0)
+ if (strcmp(table_type, "VIEW") == 0)
DBUG_VOID_RETURN;
/* Check --no-data flag */
@@ -2397,6 +3094,18 @@ static void dump_table(char *table, char *db)
DBUG_VOID_RETURN;
}
+ /*
+ Check --skip-events flag: it is not enough to skip creation of events
+ discarding SHOW CREATE EVENT statements generation. The myslq.event
+ table data should be skipped too.
+ */
+ if (!opt_events && !my_strcasecmp(&my_charset_latin1, db, "mysql") &&
+ !my_strcasecmp(&my_charset_latin1, table, "event"))
+ {
+ verbose_msg("-- Skipping data table mysql.event, --skip-events was used\n");
+ DBUG_VOID_RETURN;
+ }
+
result_table= quote_name(table,table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
@@ -2455,6 +3164,7 @@ static void dump_table(char *table, char *db)
if (mysql_real_query(mysql, query_string.str, query_string.length))
{
DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
+ dynstr_free(&query_string);
DBUG_VOID_RETURN;
}
}
@@ -2641,7 +3351,7 @@ static void dump_table(char *table, char *db)
dynstr_append_checked(&extended_row, "NULL");
else
{
- if (field->type == FIELD_TYPE_DECIMAL)
+ if (field->type == MYSQL_TYPE_DECIMAL)
{
/* add " signs around */
dynstr_append_checked(&extended_row, "'");
@@ -2710,7 +3420,7 @@ static void dump_table(char *table, char *db)
else if (my_isalpha(charset_info, *ptr) ||
(*ptr == '-' && my_isalpha(charset_info, ptr[1])))
fputs("NULL", md_result_file);
- else if (field->type == FIELD_TYPE_DECIMAL)
+ else if (field->type == MYSQL_TYPE_DECIMAL)
{
/* add " signs around */
fputc('\'', md_result_file);
@@ -2809,8 +3519,8 @@ static void dump_table(char *table, char *db)
check_io(md_result_file);
}
mysql_free_result(res);
- dynstr_free(&query_string);
}
+ dynstr_free(&query_string);
DBUG_VOID_RETURN;
err:
@@ -2844,6 +3554,263 @@ static char *getTableName(int reset)
} /* getTableName */
+/*
+ dump all logfile groups and tablespaces
+*/
+
+static int dump_all_tablespaces()
+{
+ return dump_tablespaces(NULL);
+}
+
+static int dump_tablespaces_for_tables(char *db, char **table_names, int tables)
+{
+ DYNAMIC_STRING where;
+ int r;
+ int i;
+ char name_buff[NAME_LEN*2+3];
+
+ mysql_real_escape_string(mysql, name_buff, db, strlen(db));
+
+ init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN ("
+ "SELECT DISTINCT TABLESPACE_NAME FROM"
+ " INFORMATION_SCHEMA.PARTITIONS"
+ " WHERE"
+ " TABLE_SCHEMA='", 256, 1024);
+ dynstr_append_checked(&where, name_buff);
+ dynstr_append_checked(&where, "' AND TABLE_NAME IN (");
+
+ for (i=0 ; i<tables ; i++)
+ {
+ mysql_real_escape_string(mysql, name_buff,
+ table_names[i], strlen(table_names[i]));
+
+ dynstr_append_checked(&where, "'");
+ dynstr_append_checked(&where, name_buff);
+ dynstr_append_checked(&where, "',");
+ }
+ dynstr_trunc(&where, 1);
+ dynstr_append_checked(&where,"))");
+
+ DBUG_PRINT("info",("Dump TS for Tables where: %s",where.str));
+ r= dump_tablespaces(where.str);
+ dynstr_free(&where);
+ return r;
+}
+
+static int dump_tablespaces_for_databases(char** databases)
+{
+ DYNAMIC_STRING where;
+ int r;
+ int i;
+
+ init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN ("
+ "SELECT DISTINCT TABLESPACE_NAME FROM"
+ " INFORMATION_SCHEMA.PARTITIONS"
+ " WHERE"
+ " TABLE_SCHEMA IN (", 256, 1024);
+
+ for (i=0 ; databases[i]!=NULL ; i++)
+ {
+ char db_name_buff[NAME_LEN*2+3];
+ mysql_real_escape_string(mysql, db_name_buff,
+ databases[i], strlen(databases[i]));
+ dynstr_append_checked(&where, "'");
+ dynstr_append_checked(&where, db_name_buff);
+ dynstr_append_checked(&where, "',");
+ }
+ dynstr_trunc(&where, 1);
+ dynstr_append_checked(&where,"))");
+
+ DBUG_PRINT("info",("Dump TS for DBs where: %s",where.str));
+ r= dump_tablespaces(where.str);
+ dynstr_free(&where);
+ return r;
+}
+
+static int dump_tablespaces(char* ts_where)
+{
+ MYSQL_ROW row;
+ MYSQL_RES *tableres;
+ char buf[FN_REFLEN];
+ DYNAMIC_STRING sqlbuf;
+ int first= 0;
+ /*
+ The following are used for parsing the EXTRA field
+ */
+ char extra_format[]= "UNDO_BUFFER_SIZE=";
+ char *ubs;
+ char *endsemi;
+ DBUG_ENTER("dump_tablespaces");
+
+ init_dynamic_string_checked(&sqlbuf,
+ "SELECT LOGFILE_GROUP_NAME,"
+ " FILE_NAME,"
+ " TOTAL_EXTENTS,"
+ " INITIAL_SIZE,"
+ " ENGINE,"
+ " EXTRA"
+ " FROM INFORMATION_SCHEMA.FILES"
+ " WHERE FILE_TYPE = 'UNDO LOG'"
+ " AND FILE_NAME IS NOT NULL",
+ 256, 1024);
+ if(ts_where)
+ {
+ dynstr_append_checked(&sqlbuf,
+ " AND LOGFILE_GROUP_NAME IN ("
+ "SELECT DISTINCT LOGFILE_GROUP_NAME"
+ " FROM INFORMATION_SCHEMA.FILES"
+ " WHERE FILE_TYPE = 'DATAFILE'"
+ );
+ dynstr_append_checked(&sqlbuf, ts_where);
+ dynstr_append_checked(&sqlbuf, ")");
+ }
+ dynstr_append_checked(&sqlbuf,
+ " GROUP BY LOGFILE_GROUP_NAME, FILE_NAME"
+ ", ENGINE"
+ " ORDER BY LOGFILE_GROUP_NAME");
+
+ if (mysql_query(mysql, sqlbuf.str) ||
+ !(tableres = mysql_store_result(mysql)))
+ {
+ dynstr_free(&sqlbuf);
+ if (mysql_errno(mysql) == ER_BAD_TABLE_ERROR ||
+ mysql_errno(mysql) == ER_BAD_DB_ERROR ||
+ mysql_errno(mysql) == ER_UNKNOWN_TABLE)
+ {
+ fprintf(md_result_file,
+ "\n--\n-- Not dumping tablespaces as no INFORMATION_SCHEMA.FILES"
+ " table on this server\n--\n");
+ check_io(md_result_file);
+ DBUG_RETURN(0);
+ }
+
+ my_printf_error(0, "Error: '%s' when trying to dump tablespaces",
+ MYF(0), mysql_error(mysql));
+ DBUG_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)
+ {
+ ubs= strstr(row[5],extra_format);
+ if(!ubs)
+ break;
+ ubs+= strlen(extra_format);
+ endsemi= strstr(ubs,";");
+ if(endsemi)
+ endsemi[0]= '\0';
+ fprintf(md_result_file,
+ " UNDO_BUFFER_SIZE %s\n",
+ ubs);
+ }
+ 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);
+ }
+ }
+ dynstr_free(&sqlbuf);
+ mysql_free_result(tableres);
+ init_dynamic_string_checked(&sqlbuf,
+ "SELECT DISTINCT TABLESPACE_NAME,"
+ " FILE_NAME,"
+ " LOGFILE_GROUP_NAME,"
+ " EXTENT_SIZE,"
+ " INITIAL_SIZE,"
+ " ENGINE"
+ " FROM INFORMATION_SCHEMA.FILES"
+ " WHERE FILE_TYPE = 'DATAFILE'",
+ 256, 1024);
+
+ if(ts_where)
+ dynstr_append_checked(&sqlbuf, ts_where);
+
+ dynstr_append_checked(&sqlbuf, " ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME");
+
+ if (mysql_query_with_error_report(mysql, &tableres, sqlbuf.str))
+ {
+ dynstr_free(&sqlbuf);
+ DBUG_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);
+ }
+ }
+
+ mysql_free_result(tableres);
+ dynstr_free(&sqlbuf);
+ DBUG_RETURN(0);
+}
+
static int dump_all_databases()
{
MYSQL_ROW row;
@@ -2928,8 +3895,11 @@ RETURN VALUES
0 Success.
1 Failure.
*/
+
int init_dumping_tables(char *qdatabase)
{
+ DBUG_ENTER("init_dumping_tables");
+
if (!opt_create_db)
{
char qbuf[256];
@@ -2962,10 +3932,10 @@ int init_dumping_tables(char *qdatabase)
{
fprintf(md_result_file,"\n%s;\n",row[1]);
}
+ mysql_free_result(dbinfo);
}
}
-
- return 0;
+ DBUG_RETURN(0);
} /* init_dumping_tables */
@@ -3010,9 +3980,9 @@ static int init_dumping(char *database, int init_func(char*))
/* Return 1 if we should copy the table */
-my_bool include_table(byte* hash_key, uint len)
+my_bool include_table(const uchar *hash_key, size_t len)
{
- return !hash_search(&ignore_table, (byte*) hash_key, len);
+ return !hash_search(&ignore_table, hash_key, len);
}
@@ -3037,10 +4007,15 @@ static int dump_all_tables_in_db(char *database)
{
DYNAMIC_STRING query;
init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
- for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
+ for (numrows= 0 ; (table= getTableName(1)) ; )
{
- dynstr_append_checked(&query, quote_name(table, table_buff, 1));
- dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
+ char *end= strmov(afterdot, table);
+ if (include_table((uchar*) hash_key,end - hash_key))
+ {
+ numrows++;
+ dynstr_append_checked(&query, quote_name(table, table_buff, 1));
+ dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
+ }
}
if (numrows && mysql_real_query(mysql, query.str, query.length-1))
DB_error(mysql, "when using LOCK TABLES");
@@ -3056,16 +4031,29 @@ static int dump_all_tables_in_db(char *database)
while ((table= getTableName(0)))
{
char *end= strmov(afterdot, table);
- if (include_table(hash_key, (uint) (end - hash_key)))
+ if (include_table((uchar*) hash_key, end - hash_key))
{
dump_table(table,database);
my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
order_by= 0;
if (opt_dump_triggers && ! opt_xml &&
mysql_get_server_version(mysql) >= 50009)
- dump_triggers_for_table(table, database);
+ {
+ if (dump_triggers_for_table(table, database))
+ {
+ if (path)
+ my_fclose(md_result_file, MYF(MY_WME));
+ maybe_exit(EX_MYSQLERR);
+ }
+ }
}
}
+ if (opt_events && !opt_xml &&
+ mysql_get_server_version(mysql) >= 50106)
+ {
+ DBUG_PRINT("info", ("Dumping events for database %s", database));
+ dump_events_for_db(database);
+ }
if (opt_routines && !opt_xml &&
mysql_get_server_version(mysql) >= 50009)
{
@@ -3208,7 +4196,7 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
static int dump_selected_tables(char *db, char **table_names, int tables)
{
- char table_buff[NAME_LEN*+3];
+ char table_buff[NAME_LEN*2+3];
DYNAMIC_STRING lock_tables_query;
MEM_ROOT root;
char **dump_tables, **pos, **end;
@@ -3237,8 +4225,13 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
}
else
{
- maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
- /* We shall countinue here, if --force was given */
+ if (!ignore_errors)
+ {
+ dynstr_free(&lock_tables_query);
+ free_root(&root, MYF(0));
+ }
+ maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
+ /* We shall countinue here, if --force was given */
}
}
end= pos;
@@ -3247,14 +4240,25 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
{
if (mysql_real_query(mysql, lock_tables_query.str,
lock_tables_query.length-1))
+ {
+ if (!ignore_errors)
+ {
+ dynstr_free(&lock_tables_query);
+ free_root(&root, MYF(0));
+ }
DB_error(mysql, "when doing LOCK TABLES");
/* We shall countinue here, if --force was given */
+ }
}
dynstr_free(&lock_tables_query);
if (flush_logs)
{
if (mysql_refresh(mysql, REFRESH_LOG))
+ {
+ if (!ignore_errors)
+ free_root(&root, MYF(0));
DB_error(mysql, "when doing refresh");
+ }
/* We shall countinue here, if --force was given */
}
if (opt_xml)
@@ -3267,7 +4271,14 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
dump_table(*pos, db);
if (opt_dump_triggers &&
mysql_get_server_version(mysql) >= 50009)
- dump_triggers_for_table(*pos, db);
+ {
+ if (dump_triggers_for_table(*pos, db))
+ {
+ if (path)
+ my_fclose(md_result_file, MYF(MY_WME));
+ maybe_exit(EX_MYSQLERR);
+ }
+ }
}
/* Dump each selected view */
@@ -3276,6 +4287,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(mysql) >= 50106)
+ {
+ DBUG_PRINT("info", ("Dumping events for database %s", db));
+ dump_events_for_db(db);
+ }
/* obtain dump of routines (procs/functions) */
if (opt_routines && !opt_xml &&
mysql_get_server_version(mysql) >= 50009)
@@ -3348,7 +4365,10 @@ static int do_flush_tables_read_lock(MYSQL *mysql_con)
update starts between the two FLUSHes, we have that bad stall.
*/
return
- ( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") ||
+ ( mysql_query_with_error_report(mysql_con, 0,
+ ((opt_master_data != 0) ?
+ "FLUSH /*!40101 LOCAL */ TABLES" :
+ "FLUSH TABLES")) ||
mysql_query_with_error_report(mysql_con, 0,
"FLUSH TABLES WITH READ LOCK") );
}
@@ -3577,7 +4597,8 @@ char check_if_ignore_table(const char *table_name, char *table_type)
If these two types, we do want to skip dumping the table
*/
if (!opt_no_data &&
- (!strcmp(table_type,"MRG_MyISAM") || !strcmp(table_type,"MRG_ISAM") ||
+ (!my_strcasecmp(&my_charset_latin1, table_type, "MRG_MyISAM") ||
+ !strcmp(table_type,"MRG_ISAM") ||
!strcmp(table_type,"FEDERATED")))
result= IGNORE_DATA;
}
@@ -3639,7 +4660,7 @@ static char *primary_key_fields(const char *table_name)
do
{
quoted_field= quote_name(row[4], buff, 0);
- result_length+= (uint) strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
+ result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
} while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1);
}
@@ -3699,8 +4720,7 @@ static int replace(DYNAMIC_STRING *ds_str,
return 1;
init_dynamic_string_checked(&ds_tmp, "",
ds_str->length + replace_len, 256);
- dynstr_append_mem_checked(&ds_tmp, ds_str->str,
- (uint) (start - ds_str->str));
+ dynstr_append_mem_checked(&ds_tmp, ds_str->str, start - ds_str->str);
dynstr_append_mem_checked(&ds_tmp, replace_str, replace_len);
dynstr_append_checked(&ds_tmp, start + search_len);
dynstr_set_checked(ds_str, ds_tmp.str);
@@ -3747,14 +4767,22 @@ static my_bool get_view_structure(char *table, char* db)
result_table= quote_name(table, table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
+ if (switch_character_set_results(mysql, "binary"))
+ DBUG_RETURN(1);
+
my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %s", result_table);
+
if (mysql_query_with_error_report(mysql, &table_res, query))
+ {
+ switch_character_set_results(mysql, default_charset);
DBUG_RETURN(0);
+ }
/* Check if this is a view */
field= mysql_fetch_field_direct(table_res, 0);
if (strcmp(field->name, "View") != 0)
{
+ switch_character_set_results(mysql, default_charset);
verbose_msg("-- It's base table, skipped\n");
DBUG_RETURN(0);
}
@@ -3762,7 +4790,7 @@ static my_bool get_view_structure(char *table, char* db)
/* If requested, open separate .sql file for this view */
if (path)
{
- if (!(sql_file= open_sql_file_for_table(table)))
+ if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
DBUG_RETURN(1);
write_header(sql_file, db);
@@ -3784,9 +4812,11 @@ static my_bool get_view_structure(char *table, char* db)
my_snprintf(query, sizeof(query),
- "SELECT CHECK_OPTION, DEFINER, SECURITY_TYPE " \
- "FROM information_schema.views " \
+ "SELECT CHECK_OPTION, DEFINER, SECURITY_TYPE, "
+ " CHARACTER_SET_CLIENT, COLLATION_CONNECTION "
+ "FROM information_schema.views "
"WHERE table_name=\"%s\" AND table_schema=\"%s\"", table, db);
+
if (mysql_query(mysql, query))
{
/*
@@ -3816,6 +4846,9 @@ static my_bool get_view_structure(char *table, char* db)
if (!(table_res= mysql_store_result(mysql)) ||
!(row= mysql_fetch_row(table_res)))
{
+ if (table_res)
+ mysql_free_result(table_res);
+ dynstr_free(&ds_view);
DB_error(mysql, "when trying to save the result of SHOW CREATE TABLE in ds_view.");
DBUG_RETURN(1);
}
@@ -3843,10 +4876,10 @@ static my_bool get_view_structure(char *table, char* db)
Surround it with !50013 comments
*/
{
- uint user_name_len;
+ size_t user_name_len;
char user_name_str[USERNAME_LENGTH + 1];
char quoted_user_name_str[USERNAME_LENGTH * 2 + 3];
- uint host_name_len;
+ size_t host_name_len;
char host_name_str[HOSTNAME_LENGTH + 1];
char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
@@ -3872,12 +4905,31 @@ static my_bool get_view_structure(char *table, char* db)
}
/* Dump view structure to file */
- fprintf(sql_file, "/*!50001 %s */;\n", ds_view.str);
+
+ fprintf(sql_file,
+ "/*!50001 SET @saved_cs_client = @@character_set_client */;\n"
+ "/*!50001 SET @saved_cs_results = @@character_set_results */;\n"
+ "/*!50001 SET @saved_col_connection = @@collation_connection */;\n"
+ "/*!50001 SET character_set_client = %s */;\n"
+ "/*!50001 SET character_set_results = %s */;\n"
+ "/*!50001 SET collation_connection = %s */;\n"
+ "/*!50001 %s */;\n"
+ "/*!50001 SET character_set_client = @saved_cs_client */;\n"
+ "/*!50001 SET character_set_results = @saved_cs_results */;\n"
+ "/*!50001 SET collation_connection = @saved_col_connection */;\n",
+ (const char *) row[3],
+ (const char *) row[3],
+ (const char *) row[4],
+ (const char *) ds_view.str);
+
check_io(sql_file);
mysql_free_result(table_res);
dynstr_free(&ds_view);
}
+ if (switch_character_set_results(mysql, default_charset))
+ DBUG_RETURN(1);
+
/* If a separate .sql file was opened, close it now */
if (sql_file != md_result_file)
{
@@ -3985,16 +5037,27 @@ 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)
+ {
+ if (!opt_alltspcs && !opt_notspcs)
+ dump_all_tablespaces();
dump_all_databases();
+ }
else if (argc > 1 && !opt_databases)
{
/* Only one database and selected table(s) */
+ if (!opt_alltspcs && !opt_notspcs)
+ dump_tablespaces_for_tables(*argv, (argv + 1), (argc -1));
dump_selected_tables(*argv, (argv + 1), (argc - 1));
}
else
{
/* One or more databases, all tables */
+ if (!opt_alltspcs && !opt_notspcs)
+ dump_tablespaces_for_databases(argv);
dump_databases(argv);
}