1
/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
2
* Copyright (C) 2010 Vijay Samuel
3
* Copyright (C) 2010 Andrew Hutchings
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1
/* Copyright (C) 2008 Drizzle Open Source Development Project
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
16
/* drizzledump.cc - Dump a tables contents and format to an ASCII file
20
* Derived from mysqldump, which originally came from:
22
** The author's original notes follow :-
24
** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
25
** DATE: December 3, 1994
26
** WARRANTY: None, expressed, impressed, implied
28
** STATUS: Public domain
30
* and more work by Monty, Jani & Sinisa
31
* and all the MySQL developers over the years.
18
** The author's original notes follow :-
20
** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
21
** DATE: December 3, 1994
22
** WARRANTY: None, expressed, impressed, implied
24
** STATUS: Public domain
27
#define DUMP_VERSION "10.13"
34
31
#include "client_priv.h"
33
#include <mysys/my_sys.h>
34
#include <mystrings/m_string.h>
35
#include <mystrings/m_ctype.h>
36
#include <mysys/hash.h>
37
37
#include <stdarg.h>
38
#include <boost/unordered_set.hpp>
41
#include <drizzled/gettext.h>
42
#include <drizzled/configmake.h>
43
39
#include <drizzled/error.h>
44
#include <boost/program_options.hpp>
45
#include <boost/regex.hpp>
46
#include <boost/date_time/posix_time/posix_time.hpp>
47
#include "drizzledump_data.h"
48
#include "drizzledump_mysql.h"
49
#include "drizzledump_drizzle.h"
51
41
using namespace std;
52
using namespace drizzled;
53
namespace po= boost::program_options;
58
45
#define EX_DRIZZLEERR 2
46
#define EX_CONSCHECK 3
59
48
#define EX_EOF 5 /* ferror for output file was got */
62
static bool use_drizzle_protocol= false;
63
bool ignore_errors= false;
64
static bool flush_logs= false;
65
static bool create_options= true;
66
static bool opt_quoted= false;
67
bool opt_databases= false;
68
bool opt_alldbs= false;
69
static bool opt_lock_all_tables= false;
70
static bool opt_dump_date= true;
71
bool opt_autocommit= false;
72
static bool opt_single_transaction= false;
73
static bool opt_comments;
74
static bool opt_compact;
75
bool opt_ignore= false;
76
bool opt_drop_database;
77
bool opt_no_create_info;
78
bool opt_no_data= false;
79
bool opt_create_db= false;
80
bool opt_disable_keys= true;
81
bool extended_insert= true;
82
bool opt_replace_into= false;
84
bool opt_data_is_mangled= false;
85
uint32_t show_progress_size= 0;
49
#define EX_ILLEGAL_TABLE 6
51
/* index into 'show fields from table' */
53
#define SHOW_FIELDNAME 0
56
#define SHOW_DEFAULT 4
59
/* Size of buffer for dump's select query */
60
#define QUERY_LENGTH 1536
62
/* ignore table flags */
63
#define IGNORE_NONE 0x00 /* no ignore */
64
#define IGNORE_DATA 0x01 /* don't dump data for this table */
65
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
67
static void add_load_option(string &str, const char *option,
68
const char *option_value);
69
static uint32_t find_set(TYPELIB *lib, const char *x, uint length,
70
char **err_pos, uint *err_len);
72
static void field_escape(string &in, const char *from);
73
static bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
74
quick= 1, extended_insert= 1,
75
lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0,
76
opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
77
opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
78
opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,
79
opt_set_charset=0, opt_dump_date=1,
80
opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
81
opt_delete_master_logs=0, tty_password=0,
82
opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
83
opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
84
opt_complete_insert= 0, opt_drop_database= 0,
86
opt_routines=0, opt_tz_utc=1,
88
opt_include_master_host_port= 0,
90
opt_alltspcs=0, opt_notspcs= 0;
91
static bool debug_info_flag= 0, debug_check_flag= 0;
92
static uint32_t opt_max_allowed_packet, opt_net_buffer_length;
93
static DRIZZLE drizzle_connection,*drizzle=0;
86
94
static string insert_pat;
87
static uint32_t opt_drizzle_port= 0;
88
static int first_error= 0;
95
static char *opt_password=0,*current_user=0,
96
*current_host=0,*path=0,*fields_terminated=0,
97
*lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
98
*where=0, *order_by=0,
99
*opt_compatible_mode_str= 0,
101
*log_error_file= NULL;
102
static char **defaults_argv= 0;
103
static char compatible_mode_normal_str[255];
104
/* Server supports character_set_results session variable? */
105
static bool server_supports_switching_charsets= true;
106
static uint32_t opt_compatible_mode= 0;
107
#define DRIZZLE_OPT_MASTER_DATA_EFFECTIVE_SQL 1
108
#define DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL 2
109
#define DRIZZLE_OPT_SLAVE_DATA_EFFECTIVE_SQL 1
110
#define DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL 2
111
static uint opt_drizzle_port= 0, opt_master_data;
112
static uint opt_slave_data;
113
static uint my_end_arg;
114
static int first_error=0;
89
115
static string extended_row;
90
116
FILE *md_result_file= 0;
91
FILE *stderror_file= 0;
92
std::vector<DrizzleDumpDatabase*> database_store;
93
DrizzleDumpConnection* db_connection;
94
DrizzleDumpConnection* destination_connection;
102
int opt_destination= DESTINATION_STDOUT;
103
std::string opt_destination_host;
104
uint16_t opt_destination_port;
105
std::string opt_destination_user;
106
std::string opt_destination_password;
107
std::string opt_destination_database;
109
const string progname= "drizzledump";
121
boost::unordered_set<string> ignore_table;
123
void maybe_exit(int error);
117
FILE *stderror_file=0;
120
Constant for detection of default value of default_charset.
121
If default_charset is equal to drizzle_universal_client_charset, then
122
it is the default value which assigned at the very beginning of main().
124
static const char *drizzle_universal_client_charset=
125
DRIZZLE_UNIVERSAL_CLIENT_CHARSET;
126
static char *default_charset;
127
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
128
const char *default_dbug_option="d:t:o,/tmp/drizzledump.trace";
129
/* have we seen any VIEWs during table scanning? */
131
const char *compatible_mode_names[]=
133
"MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
134
"MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
138
#define MASK_ANSI_QUOTES \
140
(1<<2) | /* POSTGRESQL */\
141
(1<<3) | /* ORACLE */\
142
(1<<4) | /* MSSQL */\
144
(1<<6) | /* MAXDB */\
147
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
148
"", compatible_mode_names, NULL};
152
static struct my_option my_long_options[] =
154
{"all", 'a', "Deprecated. Use --create-options instead.",
155
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
157
{"all-databases", 'A',
158
"Dump all the databases. This will be same as --databases with all databases selected.",
159
(char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
161
{"all-tablespaces", 'Y',
162
"Dump all the tablespaces.",
163
(char**) &opt_alltspcs, (char**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
165
{"no-tablespaces", 'y',
166
"Do not dump any tablespace information.",
167
(char**) &opt_notspcs, (char**) &opt_notspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
169
{"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
170
(char**) &opt_drop_database, (char**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
172
{"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
173
(char**) &opt_drop, (char**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
175
{"add-locks", OPT_LOCKS, "Add locks around insert statements.",
176
(char**) &opt_lock, (char**) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
178
{"allow-keywords", OPT_KEYWORDS,
179
"Allow creation of column names that are keywords.", (char**) &opt_keywords,
180
(char**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
181
{"apply-slave-statements", OPT_DRIZZLEDUMP_SLAVE_APPLY,
182
"Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
183
(char**) &opt_slave_apply, (char**) &opt_slave_apply, 0, GET_BOOL, NO_ARG,
185
{"character-sets-dir", OPT_CHARSETS_DIR,
186
"Directory where character sets are.", (char**) &charsets_dir,
187
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
188
{"comments", 'i', "Write additional information.",
189
(char**) &opt_comments, (char**) &opt_comments, 0, GET_BOOL, NO_ARG,
191
{"compatible", OPT_COMPATIBLE,
192
"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 DRIZZLE server version 4.1.0 or higher. This option is ignored with earlier server versions.",
193
(char**) &opt_compatible_mode_str, (char**) &opt_compatible_mode_str, 0,
194
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
195
{"compact", OPT_COMPACT,
196
"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",
197
(char**) &opt_compact, (char**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
199
{"complete-insert", 'c', "Use complete insert statements.",
200
(char**) &opt_complete_insert, (char**) &opt_complete_insert, 0, GET_BOOL,
201
NO_ARG, 0, 0, 0, 0, 0, 0},
202
{"compress", 'C', "Use compression in server/client protocol.",
203
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
205
{"create-options", OPT_CREATE_OPTIONS,
206
"Include all DRIZZLE specific create options.",
207
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
210
"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.",
211
(char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
213
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
214
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
215
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
216
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
217
(char**) &debug_info_flag, (char**) &debug_info_flag,
218
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
219
{"default-character-set", OPT_DEFAULT_CHARSET,
220
"Set the default character set.", (char**) &default_charset,
221
(char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
222
{"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
223
(char**) &opt_delayed, (char**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
225
{"delete-master-logs", OPT_DELETE_MASTER_LOGS,
226
"Delete logs on master after backup. This automatically enables --master-data.",
227
(char**) &opt_delete_master_logs, (char**) &opt_delete_master_logs, 0,
228
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
229
{"disable-keys", 'K',
230
"'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (char**) &opt_disable_keys,
231
(char**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
232
{"dump-slave", OPT_DRIZZLEDUMP_SLAVE_DATA,
233
"This causes the binary log position and filename of the master to be "
234
"appended to the dumped data output. Setting the value to 1, will print"
235
"it as a CHANGE MASTER command in the dumped data output; if equal"
236
" to 2, that command will be prefixed with a comment symbol. "
237
"This option will turn --lock-all-tables on, unless "
238
"--single-transaction is specified too (in which case a "
239
"global read lock is only taken a short time at the beginning of the dump "
240
"- don't forget to read about --single-transaction below). In all cases "
241
"any action on logs will happen at the exact moment of the dump."
242
"Option automatically turns --lock-tables off.",
243
(char**) &opt_slave_data, (char**) &opt_slave_data, 0,
244
GET_UINT, OPT_ARG, 0, 0, DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0},
245
{"events", 'E', "Dump events.",
246
(char**) &opt_events, (char**) &opt_events, 0, GET_BOOL,
247
NO_ARG, 0, 0, 0, 0, 0, 0},
248
{"extended-insert", 'e',
249
"Allows utilization of the new, much faster INSERT syntax.",
250
(char**) &extended_insert, (char**) &extended_insert, 0, GET_BOOL, NO_ARG,
252
{"fields-terminated-by", OPT_FTB,
253
"Fields in the textfile are terminated by ...", (char**) &fields_terminated,
254
(char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
255
{"fields-enclosed-by", OPT_ENC,
256
"Fields in the importfile are enclosed by ...", (char**) &enclosed,
257
(char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
258
{"fields-optionally-enclosed-by", OPT_O_ENC,
259
"Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
260
(char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
261
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
262
(char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
263
{"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
264
(char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
266
{"flush-logs", 'F', "Flush logs file in server before starting dump. "
267
"Note that if you dump many databases at once (using the option "
268
"--databases= or --all-databases), the logs will be flushed for "
269
"each database dumped. The exception is when using --lock-all-tables "
271
"in this case the logs will be flushed only once, corresponding "
272
"to the moment all tables are locked. So if you want your dump and "
273
"the log flush to happen at the same exact moment you should use "
274
"--lock-all-tables or --master-data with --flush-logs",
275
(char**) &flush_logs, (char**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
277
{"flush-privileges", OPT_ESC, "Emit a FLUSH PRIVILEGES statement "
278
"after dumping the DRIZZLE database. This option should be used any "
279
"time the dump contains the DRIZZLE database and any other database "
280
"that depends on the data in the DRIZZLE database for proper restore. ",
281
(char**) &flush_privileges, (char**) &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
283
{"force", 'f', "Continue even if we get an sql-error.",
284
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG,
286
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
287
NO_ARG, 0, 0, 0, 0, 0, 0},
288
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
289
"VARBINARY, BLOB) in hexadecimal format.",
290
(char**) &opt_hex_blob, (char**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
291
{"host", 'h', "Connect to host.", (char**) ¤t_host,
292
(char**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
293
{"ignore-table", OPT_IGNORE_TABLE,
294
"Do not dump the specified table. To specify more than one table to ignore, "
295
"use the directive multiple times, once for each table. Each table must "
296
"be specified with both database and table names, e.g. --ignore-table=database.table",
297
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
298
{"include-master-host-port", OPT_DRIZZLEDUMP_INCLUDE_MASTER_HOST_PORT,
299
"Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' in dump produced with --dump-slave.",
300
(char**) &opt_include_master_host_port,
301
(char**) &opt_include_master_host_port,
304
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
305
(char**) &opt_ignore, (char**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
307
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
308
(char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
309
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
310
{"lock-all-tables", 'x', "Locks all tables across all databases. This "
311
"is achieved by taking a global read lock for the duration of the whole "
312
"dump. Automatically turns --single-transaction and --lock-tables off.",
313
(char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
315
{"lock-tables", 'l', "Lock all tables for read.", (char**) &lock_tables,
316
(char**) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
317
{"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.",
318
(char**) &log_error_file, (char**) &log_error_file, 0, GET_STR,
319
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
320
{"master-data", OPT_MASTER_DATA,
321
"This causes the binary log position and filename to be appended to the "
322
"output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
323
" to 2, that command will be prefixed with a comment symbol. "
324
"This option will turn --lock-all-tables on, unless "
325
"--single-transaction is specified too (in which case a "
326
"global read lock is only taken a short time at the beginning of the dump "
327
"- don't forget to read about --single-transaction below). In all cases "
328
"any action on logs will happen at the exact moment of the dump."
329
"Option automatically turns --lock-tables off.",
330
(char**) &opt_master_data, (char**) &opt_master_data, 0,
331
GET_UINT, OPT_ARG, 0, 0, DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
332
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
333
(char**) &opt_max_allowed_packet, (char**) &opt_max_allowed_packet, 0,
334
GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
335
(int64_t) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
336
{"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
337
(char**) &opt_net_buffer_length, (char**) &opt_net_buffer_length, 0,
338
GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
339
MALLOC_OVERHEAD-1024, 1024, 0},
340
{"no-autocommit", OPT_AUTOCOMMIT,
341
"Wrap tables with autocommit/commit statements.",
342
(char**) &opt_autocommit, (char**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
344
{"no-create-db", 'n',
345
"'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.}.",
346
(char**) &opt_create_db, (char**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
348
{"no-create-info", 't', "Don't write table creation info.",
349
(char**) &opt_no_create_info, (char**) &opt_no_create_info, 0, GET_BOOL,
350
NO_ARG, 0, 0, 0, 0, 0, 0},
351
{"no-data", 'd', "No row information.", (char**) &opt_no_data,
352
(char**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
353
{"no-set-names", 'N',
354
"Deprecated. Use --skip-set-charset instead.",
355
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
356
{"opt", OPT_OPTIMIZE,
357
"Same as --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys. Enabled by default, disable with --skip-opt.",
358
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
359
{"order-by-primary", OPT_ORDER_BY_PRIMARY,
360
"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.",
361
(char**) &opt_order_by_primary, (char**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
363
"Password to use when connecting to server. If password is not given it's solicited on the tty.",
364
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
365
{"port", 'P', "Port number to use for connection.", (char**) &opt_drizzle_port,
366
(char**) &opt_drizzle_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
368
{"quick", 'q', "Don't buffer query, dump directly to stdout.",
369
(char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
370
{"quote-names",'Q', "Quote table and column names with backticks (`).",
371
(char**) &opt_quoted, (char**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
373
{"replace", OPT_DRIZZLE_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
374
(char**) &opt_replace_into, (char**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
377
"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).",
378
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
379
{"routines", 'R', "Dump stored routines (functions and procedures).",
380
(char**) &opt_routines, (char**) &opt_routines, 0, GET_BOOL,
381
NO_ARG, 0, 0, 0, 0, 0, 0},
382
{"set-charset", OPT_SET_CHARSET,
383
"Add 'SET NAMES default_character_set' to the output.",
384
(char**) &opt_set_charset, (char**) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
386
{"set-variable", 'O',
387
"Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
388
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
390
Note that the combination --single-transaction --master-data
391
will give bullet-proof binlog position only if server >=4.1.3. That's the
392
old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug.
394
{"single-transaction", OPT_TRANSACTION,
395
"Creates a consistent snapshot by dumping all tables in a single "
396
"transaction. Works ONLY for tables stored in storage engines which "
397
"support multiversioning (currently only InnoDB does); the dump is NOT "
398
"guaranteed to be consistent for other storage engines. "
399
"While a --single-transaction dump is in process, to ensure a valid "
400
"dump file (correct table contents and binary log position), no other "
401
"connection should use the following statements: ALTER TABLE, DROP "
402
"TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
403
"isolated from them. Option automatically turns off --lock-tables.",
404
(char**) &opt_single_transaction, (char**) &opt_single_transaction, 0,
405
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
406
{"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
407
(char**) &opt_dump_date, (char**) &opt_dump_date, 0,
408
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
409
{"skip-opt", OPT_SKIP_OPTIMIZATION,
410
"Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
411
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
413
"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.",
414
(char**) &path, (char**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
415
{"tables", OPT_TABLES, "Overrides option --databases (-B).",
416
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
417
{"tz-utc", OPT_TZ_UTC,
418
"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.",
419
(char**) &opt_tz_utc, (char**) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
420
#ifndef DONT_ALLOW_USER_CHANGE
421
{"user", 'u', "User for login if not current user.",
422
(char**) ¤t_user, (char**) ¤t_user, 0, GET_STR, REQUIRED_ARG,
425
{"verbose", 'v', "Print info about the various stages.",
426
(char**) &verbose, (char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
427
{"version",'V', "Output version information and exit.", 0, 0, 0,
428
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
429
{"where", 'w', "Dump only selected records; QUOTES mandatory!",
430
(char**) &where, (char**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
431
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
432
NO_ARG, 0, 0, 0, 0, 0, 0},
433
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
436
static const char *load_default_groups[]= { "drizzledump","client",0 };
438
static void maybe_exit(int error);
124
439
static void die(int error, const char* reason, ...);
125
static void write_header(char *db_name);
126
static int dump_selected_tables(const string &db, const vector<string> &table_names);
127
static int dump_databases(const vector<string> &db_names);
440
static void maybe_die(int error, const char* reason, ...);
441
static void write_header(FILE *sql_file, char *db_name);
442
static void print_value(FILE *file, DRIZZLE_RES *result, DRIZZLE_ROW row,
443
const char *prefix,const char *name,
445
static int dump_selected_tables(char *db, char **table_names, int tables);
446
static int dump_all_tables_in_db(char *db);
447
static int init_dumping_tables(char *);
448
static int init_dumping(char *, int init_func(char*));
449
static int dump_databases(char **);
128
450
static int dump_all_databases(void);
129
int get_server_type();
130
void dump_all_tables(void);
131
void generate_dump(void);
132
void generate_dump_db(void);
134
void dump_all_tables(void)
136
std::vector<DrizzleDumpDatabase*>::iterator i;
137
for (i= database_store.begin(); i != database_store.end(); ++i)
139
if ((not (*i)->populateTables()) && (not ignore_errors))
140
maybe_exit(EX_DRIZZLEERR);
144
void generate_dump(void)
146
std::vector<DrizzleDumpDatabase*>::iterator i;
150
cout << endl << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;"
151
<< endl << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
155
cout << "SET AUTOCOMMIT=0;" << endl;
157
for (i= database_store.begin(); i != database_store.end(); ++i)
159
DrizzleDumpDatabase *database= *i;
165
cout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;"
166
<< endl << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
170
void generate_dump_db(void)
172
std::vector<DrizzleDumpDatabase*>::iterator i;
173
DrizzleStringBuf sbuf(1024);
176
destination_connection= new DrizzleDumpConnection(opt_destination_host,
177
opt_destination_port, opt_destination_user, opt_destination_password,
180
catch (std::exception&)
182
cerr << "Could not connect to destination database server" << endl;
183
maybe_exit(EX_DRIZZLEERR);
185
sbuf.setConnection(destination_connection);
186
std::ostream sout(&sbuf);
187
sout.exceptions(ios_base::badbit);
191
sout << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;" << endl;
192
sout << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
196
cout << "SET AUTOCOMMIT=0;" << endl;
198
for (i= database_store.begin(); i != database_store.end(); ++i)
202
DrizzleDumpDatabase *database= *i;
205
catch (std::exception&)
207
std::cout << _("Error inserting into destination database") << std::endl;
208
if (not ignore_errors)
209
maybe_exit(EX_DRIZZLEERR);
215
sout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;" << endl;
216
sout << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
451
static char *quote_name(const char *name, char *buff, bool force);
452
char check_if_ignore_table(const char *table_name, char *table_type);
453
static char *primary_key_fields(const char *table_name);
456
Print the supplied message if in verbose mode
461
... variable number of parameters
463
static void verbose_msg(const char *fmt, ...)
472
vfprintf(stderr, fmt, args);
221
479
exit with message if ferror(file)
228
486
static void check_io(FILE *file)
230
488
if (ferror(file))
231
die(EX_EOF, _("Got errno %d on write"), errno);
234
static void write_header(char *db_name)
236
if ((not opt_compact) and (opt_comments))
238
cout << "-- drizzledump " << VERSION << " libdrizzle "
239
<< drizzle_version() << ", for " << HOST_VENDOR << "-" << HOST_OS
240
<< " (" << HOST_CPU << ")" << endl << "--" << endl;
241
cout << "-- Host: " << current_host << " Database: " << db_name << endl;
242
cout << "-- ------------------------------------------------------" << endl;
243
cout << "-- Server version\t" << db_connection->getServerVersion();
244
if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
245
cout << " (MySQL server)";
246
else if (db_connection->getServerType() == ServerDetect::SERVER_DRIZZLE_FOUND)
247
cout << " (Drizzle server)";
248
cout << endl << endl;
489
die(EX_EOF, "Got errno %d on write", errno);
492
static void print_version(void)
494
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
495
drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
496
} /* print_version */
499
static void short_usage_sub(void)
501
printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
502
printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
504
printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
508
static void usage(void)
511
puts("By Igor Romanenko, Monty, Jani & Sinisa");
512
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
513
puts("Dumping definition and data DRIZZLE database or table");
515
print_defaults("my",load_default_groups);
516
my_print_help(my_long_options);
517
my_print_variables(my_long_options);
521
static void short_usage(void)
524
printf("For more options, use %s --help\n", my_progname);
527
static void write_header(FILE *sql_file, char *db_name)
531
fputs("<?xml version=\"1.0\"?>\n", sql_file);
533
Schema reference. Allows use of xsi:nil for NULL values and
534
xsi:type to define an element's data type.
536
fputs("<drizzledump ", sql_file);
537
fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
539
fputs(">\n", sql_file);
542
else if (!opt_compact)
547
"-- DRIZZLE dump %s Distrib %s, for %s (%s)\n--\n",
548
DUMP_VERSION, drizzle_get_client_info(),
549
SYSTEM_TYPE, MACHINE_TYPE);
550
fprintf(sql_file, "-- Host: %s Database: %s\n",
551
current_host ? current_host : "localhost", db_name ? db_name :
553
fputs("-- ------------------------------------------------------\n",
555
fprintf(sql_file, "-- Server version\t%s\n",
556
drizzle_get_server_info(&drizzle_connection));
560
"\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
561
"\n/*!40101 SET NAMES %s */;\n",default_charset);
565
fprintf(sql_file, "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n");
566
fprintf(sql_file, "/*!40103 SET TIME_ZONE='+00:00' */;\n");
571
fprintf(md_result_file,"\
572
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n\
573
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n\
250
578
} /* write_header */
253
581
static void write_footer(FILE *sql_file)
585
fputs("</drizzledump>\n", sql_file);
588
else if (!opt_compact)
591
fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n");
595
fprintf(md_result_file,"\
596
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
597
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
601
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
603
"/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
604
fputs("\n", sql_file);
257
605
if (opt_comments)
259
607
if (opt_dump_date)
261
boost::posix_time::ptime time(boost::posix_time::second_clock::local_time());
610
get_date(time_str, GETDATE_DATE_TIME, 0);
262
611
fprintf(sql_file, "-- Dump completed on %s\n",
263
boost::posix_time::to_simple_string(time).c_str());
266
615
fprintf(sql_file, "-- Dump completed\n");
312
900
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
315
fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
903
fprintf(stderr, "%s: %s\n", my_progname, buffer);
318
906
ignore_errors= 0; /* force the exit */
319
907
maybe_exit(error_num);
912
Prints out an error message and maybe kills the process.
916
error_num - process return value
917
fmt_reason - a format string for use by vsnprintf.
918
... - variable arguments for above fmt_reason string
921
This call prints out the formatted error message to stderr and then
922
terminates the process, unless the --force command line option is used.
924
This call should be used for non-fatal errors (such as database
925
errors) that the code may still be able to continue to the next unit
929
static void maybe_die(int error_num, const char* fmt_reason, ...)
933
va_start(args,fmt_reason);
934
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
937
fprintf(stderr, "%s: %s\n", my_progname, buffer);
940
maybe_exit(error_num);
946
Sends a query to server, optionally reads result, prints error message if
950
drizzle_query_with_error_report()
951
drizzle_con connection to use
952
res if non zero, result will be put there with
953
drizzle_store_result()
954
query query to send to server
957
0 query sending and (if res!=0) result reading went ok
961
static int drizzle_query_with_error_report(DRIZZLE *drizzle_con, DRIZZLE_RES **res,
964
if (drizzle_query(drizzle_con, query) ||
965
(res && !((*res)= drizzle_store_result(drizzle_con))))
967
maybe_die(EX_DRIZZLEERR, "Couldn't execute '%s': %s (%d)",
968
query, drizzle_error(drizzle_con), drizzle_errno(drizzle_con));
976
Switch charset for results to some specified charset. If the server does not
977
support character_set_results variable, nothing can be done here. As for
978
whether something should be done here, future new callers of this function
979
should be aware that the server lacking the facility of switching charsets is
982
@note If the server lacks support, then nothing is changed and no error
983
condition is returned.
985
@returns whether there was an error or not
987
static int switch_character_set_results(DRIZZLE *drizzle, const char *cs_name)
989
char query_buffer[QUERY_LENGTH];
992
/* Server lacks facility. This is not an error, by arbitrary decision . */
993
if (!server_supports_switching_charsets)
996
query_length= snprintf(query_buffer,
997
sizeof (query_buffer),
998
"SET SESSION character_set_results = '%s'",
999
(const char *) cs_name);
1001
return drizzle_real_query(drizzle, query_buffer, query_length);
1005
Open a new .sql file to dump the table or view into
1008
open_sql_file_for_table
1009
name name of the table or view
1012
0 Failed to open file
1013
> 0 Handle of the open file
1015
static FILE* open_sql_file_for_table(const char* table)
1018
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
1019
convert_dirname(tmp_path,path,NULL);
1020
res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
1021
O_WRONLY, MYF(MY_WME));
322
1026
static void free_resources(void)
324
1028
if (md_result_file && md_result_file != stdout)
325
fclose(md_result_file);
326
opt_password.erase();
1029
my_fclose(md_result_file, MYF(0));
1031
if (hash_inited(&ignore_table))
1032
hash_free(&ignore_table);
1034
free_defaults(defaults_argv);
330
void maybe_exit(int error)
1039
static void maybe_exit(int error)
332
1041
if (!first_error)
333
1042
first_error= error;
334
1043
if (ignore_errors)
336
delete db_connection;
337
delete destination_connection;
1046
drizzle_close(drizzle);
338
1047
free_resources();
1053
db_connect -- connects to the host and selects DB.
1056
static int connect_to_db(char *host, char *user,char *passwd)
1058
char buff[20+FN_REFLEN];
1061
verbose_msg("-- Connecting to %s...\n", host ? host : "localhost");
1062
drizzle_create(&drizzle_connection);
1064
drizzle_options(&drizzle_connection,DRIZZLE_OPT_COMPRESS,NULL);
1065
if (!(drizzle= drizzle_connect(&drizzle_connection,host,user,passwd,
1066
NULL,opt_drizzle_port, NULL,
1069
DB_error(&drizzle_connection, "when trying to connect");
1072
if (drizzle_get_server_version(&drizzle_connection) < 40100)
1074
/* Don't dump SET NAMES with a pre-4.1 server (bug#7997). */
1077
/* Don't switch charsets for 4.1 and earlier. (bug#34192). */
1078
server_supports_switching_charsets= false;
1081
set time_zone to UTC to allow dumping date types between servers with
1082
different time zone settings
1086
snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */");
1087
if (drizzle_query_with_error_report(drizzle, 0, buff))
1091
} /* connect_to_db */
1095
** dbDisconnect -- disconnects from the host.
1097
static void dbDisconnect(char *host)
1099
verbose_msg("-- Disconnecting from %s...\n", host ? host : "localhost");
1100
drizzle_close(drizzle);
1101
} /* dbDisconnect */
1104
static void unescape(FILE *file,char *pos,uint length)
1108
if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
1109
die(EX_DRIZZLEERR, "Couldn't allocate memory");
1111
drizzle_escape_string(tmp, pos, length);
1121
static bool test_if_special_chars(const char *str)
1123
for ( ; *str ; str++)
1124
if (!my_isvar(charset_info,*str) && *str != '$')
1127
} /* test_if_special_chars */
1132
quote_name(name, buff, force)
1134
Quotes char string, taking into account compatible mode
1138
name Unquoted string containing that which will be quoted
1139
buff The buffer that contains the quoted value, also returned
1140
force Flag to make it ignore 'test_if_special_chars'
1147
static char *quote_name(const char *name, char *buff, bool force)
1150
char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';
1152
if (!force && !opt_quoted && !test_if_special_chars(name))
1153
return (char*) name;
1168
Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
1172
name name of the table
1173
buff quoted name of the table
1176
Quote \, _, ' and % characters
1178
Note: Because DRIZZLE uses the C escape syntax in strings
1179
(for example, '\n' to represent newline), you must double
1180
any '\' that you use in your LIKE strings. For example, to
1181
search for '\n', specify it as '\\n'. To search for '\', specify
1182
it as '\\\\' (the backslashes are stripped once by the parser
1183
and another time when the pattern match is done, leaving a
1184
single backslash to be matched).
1186
Example: "t\1" => "t\\\\1"
1189
static char *quote_for_like(const char *name, char *buff)
1201
else if (*name == '\'' || *name == '_' || *name == '%')
1212
Quote and print a string.
1216
xml_file - output file
1217
str - string to print
1221
Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1224
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
1228
for (end= str + len; str != end; str++)
1232
fputs("<", xml_file);
1235
fputs(">", xml_file);
1238
fputs("&", xml_file);
1241
fputs(""", xml_file);
1244
fputc(*str, xml_file);
1253
Print xml tag. Optionally add attribute(s).
1256
print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
1257
..., attribute_name_n, attribute_value_n, NULL)
1258
xml_file - output file
1259
sbeg - line beginning
1260
line_end - line ending
1261
tag_name - XML tag name.
1262
first_attribute_name - tag and first attribute
1263
first_attribute_value - (Implied) value of first attribute
1264
attribute_name_n - attribute n
1265
attribute_value_n - value of attribute n
1268
Print XML tag with any number of attribute="value" pairs to the xml_file.
1271
sbeg<tag_name first_attribute_name="first_attribute_value" ...
1272
attribute_name_n="attribute_value_n">send
1274
Additional arguments must be present in attribute/value pairs.
1275
The last argument should be the null character pointer.
1276
All attribute_value arguments MUST be NULL terminated strings.
1277
All attribute_value arguments will be quoted before output.
1280
static void print_xml_tag(FILE * xml_file, const char* sbeg,
1281
const char* line_end,
1282
const char* tag_name,
1283
const char* first_attribute_name, ...)
1286
const char *attribute_name, *attribute_value;
1288
fputs(sbeg, xml_file);
1289
fputc('<', xml_file);
1290
fputs(tag_name, xml_file);
1292
va_start(arg_list, first_attribute_name);
1293
attribute_name= first_attribute_name;
1294
while (attribute_name != NULL)
1296
attribute_value= va_arg(arg_list, char *);
1297
assert(attribute_value != NULL);
1299
fputc(' ', xml_file);
1300
fputs(attribute_name, xml_file);
1301
fputc('\"', xml_file);
1303
print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
1304
fputc('\"', xml_file);
1306
attribute_name= va_arg(arg_list, char *);
1310
fputc('>', xml_file);
1311
fputs(line_end, xml_file);
1317
Print xml tag with for a field that is null
1320
print_xml_null_tag()
1321
xml_file - output file
1322
sbeg - line beginning
1323
stag_atr - tag and attribute
1324
sval - value of attribute
1325
line_end - line ending
1328
Print tag with one attribute to the xml_file. Format is:
1329
<stag_atr="sval" xsi:nil="true"/>
1331
sval MUST be a NULL terminated string.
1332
sval string will be qouted before output.
1335
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
1336
const char* stag_atr, const char* sval,
1337
const char* line_end)
1339
fputs(sbeg, xml_file);
1340
fputs("<", xml_file);
1341
fputs(stag_atr, xml_file);
1342
fputs("\"", xml_file);
1343
print_quoted_xml(xml_file, sval, strlen(sval));
1344
fputs("\" xsi:nil=\"true\" />", xml_file);
1345
fputs(line_end, xml_file);
1351
Print xml tag with many attributes.
1355
xml_file - output file
1356
row_name - xml tag name
1357
tableRes - query result
1361
Print tag with many attribute to the xml_file. Format is:
1362
\t\t<row_name Atr1="Val1" Atr2="Val2"... />
1364
All atributes and values will be quoted before output.
1367
static void print_xml_row(FILE *xml_file, const char *row_name,
1368
DRIZZLE_RES *tableRes, DRIZZLE_ROW *row)
1371
DRIZZLE_FIELD *field;
1372
uint32_t *lengths= drizzle_fetch_lengths(tableRes);
1374
fprintf(xml_file, "\t\t<%s", row_name);
1376
drizzle_field_seek(tableRes, 0);
1377
for (i= 0; (field= drizzle_fetch_field(tableRes)); i++)
1381
fputc(' ', xml_file);
1382
print_quoted_xml(xml_file, field->name, field->name_length);
1383
fputs("=\"", xml_file);
1384
print_quoted_xml(xml_file, (*row)[i], lengths[i]);
1385
fputc('"', xml_file);
1389
fputs(" />\n", xml_file);
1395
Print hex value for blob data.
1399
output_file - output file
1400
str - string to print
1404
Print hex value for blob data.
1407
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
1409
/* sakaik got the idea to to provide blob's in hex notation. */
1410
const char *ptr= str, *end= ptr + len;
1411
for (; ptr < end ; ptr++)
1412
fprintf(output_file, "%02X", *((unsigned char *)ptr));
1413
check_io(output_file);
1417
get_table_structure -- retrievs database structure, prints out corresponding
1418
CREATE statement and fills out insert_pat if the table is the type we will
1424
table_type - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
1425
ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1428
number of fields in table, 0 if error
1431
static uint get_table_structure(char *table, char *db, char *table_type,
1434
bool init=0, delayed, write_data, complete_insert;
1435
uint64_t num_fields;
1436
char *result_table, *opt_quoted_table;
1437
const char *insert_option;
1438
char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
1439
char table_buff2[NAME_LEN*2+3], query_buff[QUERY_LENGTH];
1440
FILE *sql_file= md_result_file;
1442
DRIZZLE_RES *result;
1445
*ignore_flag= check_if_ignore_table(table, table_type);
1447
delayed= opt_delayed;
1448
if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
1451
verbose_msg("-- Warning: Unable to use delayed inserts for table '%s' "
1452
"because it's of type %s\n", table, table_type);
1456
if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1458
complete_insert= opt_complete_insert;
1462
insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
1463
delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
1465
verbose_msg("-- Retrieving table structure for table %s...\n", table);
1467
len= snprintf(query_buff, sizeof(query_buff),
1468
"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
1469
(opt_quoted || opt_keywords));
1471
result_table= quote_name(table, table_buff, 1);
1472
opt_quoted_table= quote_name(table, table_buff2, 0);
1474
if (opt_order_by_primary)
1477
order_by= primary_key_fields(result_table);
1480
if (!opt_xml && !drizzle_query_with_error_report(drizzle, 0, query_buff))
1482
/* using SHOW CREATE statement */
1483
if (!opt_no_create_info)
1485
/* Make an sql-file, if path was given iow. option -T was given */
1486
char buff[20+FN_REFLEN];
1487
const DRIZZLE_FIELD *field;
1489
snprintf(buff, sizeof(buff), "show create table %s", result_table);
1491
if (switch_character_set_results(drizzle, "binary") ||
1492
drizzle_query_with_error_report(drizzle, &result, buff) ||
1493
switch_character_set_results(drizzle, default_charset))
1498
if (!(sql_file= open_sql_file_for_table(table)))
1501
write_header(sql_file, db);
1503
if (!opt_xml && opt_comments)
1505
if (strcmp (table_type, "VIEW") == 0) /* view */
1506
fprintf(sql_file, "\n--\n-- Temporary table structure for view %s\n--\n\n",
1509
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1516
Even if the "table" is a view, we do a DROP TABLE here. The
1517
view-specific code below fills in the DROP VIEW.
1519
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
1524
field= drizzle_fetch_field_direct(result, 0);
1525
if (strcmp(field->name, "View") == 0)
1527
char *scv_buff= NULL;
1529
verbose_msg("-- It's a view, create dummy table for view\n");
1531
/* save "show create" statement for later */
1532
if ((row= drizzle_fetch_row(result)) && (scv_buff=row[1]))
1533
scv_buff= my_strdup(scv_buff, MYF(0));
1535
drizzle_free_result(result);
1538
Create a table with the same name as the view and with columns of
1539
the same name in order to satisfy views that depend on this view.
1540
The table will be removed when the actual view is created.
1542
The properties of each column, aside from the data type, are not
1543
preserved in this temporary table, because they are not necessary.
1545
This will not be necessary once we can determine dependencies
1546
between views and can simply dump them in the appropriate order.
1548
snprintf(query_buff, sizeof(query_buff),
1549
"SHOW FIELDS FROM %s", result_table);
1550
if (switch_character_set_results(drizzle, "binary") ||
1551
drizzle_query_with_error_report(drizzle, &result, query_buff) ||
1552
switch_character_set_results(drizzle, default_charset))
1555
View references invalid or privileged table/col/fun (err 1356),
1556
so we cannot create a stand-in table. Be defensive and dump
1557
a comment with the view's 'show create' statement. (Bug #17371)
1560
if (drizzle_errno(drizzle) == ER_VIEW_INVALID)
1561
fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : "");
1570
if (drizzle_num_rows(result))
1575
We have already dropped any table of the same name above, so
1576
here we just drop the view.
1579
fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
1585
"/*!50001 CREATE TABLE %s (\n",
1589
Get first row, following loop will prepend comma - keeps from
1590
having to know if the row being printed is last to determine if
1591
there should be a _trailing_ comma.
1594
row= drizzle_fetch_row(result);
1596
fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0),
1599
while((row= drizzle_fetch_row(result)))
1601
/* col name, col type */
1602
fprintf(sql_file, ",\n %s %s",
1603
quote_name(row[0], name_buff, 0), row[1]);
1605
fprintf(sql_file, "\n) */;\n");
1609
drizzle_free_result(result);
1612
my_fclose(sql_file, MYF(MY_WME));
1618
row= drizzle_fetch_row(result);
1620
fprintf(sql_file, "%s;\n", row[1]);
1623
drizzle_free_result(result);
1625
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1627
if (drizzle_query_with_error_report(drizzle, &result, query_buff))
1630
my_fclose(sql_file, MYF(MY_WME));
1635
If write_data is true, then we build up insert statements for
1636
the table's data. Note: in subsequent lines of code, this test
1637
will have to be performed each time we are appending to
1642
if (opt_replace_into)
1643
insert_pat.append("REPLACE ");
1645
insert_pat.append("INSERT ");
1646
insert_pat.append(insert_option);
1647
insert_pat.append("INTO ");
1648
insert_pat.append(opt_quoted_table);
1649
if (complete_insert)
1651
insert_pat.append(" (");
1655
insert_pat.append(" VALUES ");
1656
if (!extended_insert)
1657
insert_pat.append("(");
1661
while ((row= drizzle_fetch_row(result)))
1663
if (complete_insert)
1667
insert_pat.append(", ");
1670
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1673
num_fields= drizzle_num_rows(result);
1674
drizzle_free_result(result);
1678
verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
1679
my_progname, drizzle_error(drizzle));
1681
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1683
if (drizzle_query_with_error_report(drizzle, &result, query_buff))
1686
/* Make an sql-file, if path was given iow. option -T was given */
1687
if (!opt_no_create_info)
1691
if (!(sql_file= open_sql_file_for_table(table)))
1693
write_header(sql_file, db);
1695
if (!opt_xml && opt_comments)
1696
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1699
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1701
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
1703
print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
1710
if (opt_replace_into)
1711
insert_pat.append("REPLACE ");
1713
insert_pat.append("INSERT ");
1714
insert_pat.append(insert_option);
1715
insert_pat.append("INTO ");
1716
insert_pat.append(result_table);
1717
if (complete_insert)
1718
insert_pat.append(" (");
1721
insert_pat.append(" VALUES ");
1722
if (!extended_insert)
1723
insert_pat.append("(");
1727
while ((row= drizzle_fetch_row(result)))
1729
uint32_t *lengths= drizzle_fetch_lengths(result);
1732
if (!opt_xml && !opt_no_create_info)
1734
fputs(",\n",sql_file);
1737
if (complete_insert)
1738
insert_pat.append(", ");
1741
if (complete_insert)
1742
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1743
if (!opt_no_create_info)
1747
print_xml_row(sql_file, "field", result, &row);
1752
fprintf(sql_file, " %s.%s %s", result_table,
1753
quote_name(row[SHOW_FIELDNAME],name_buff, 0),
1756
fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
1759
if (row[SHOW_DEFAULT])
1761
fputs(" DEFAULT ", sql_file);
1762
unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1764
if (!row[SHOW_NULL][0])
1765
fputs(" NOT NULL", sql_file);
1766
if (row[SHOW_EXTRA][0])
1767
fprintf(sql_file, " %s",row[SHOW_EXTRA]);
1771
num_fields= drizzle_num_rows(result);
1772
drizzle_free_result(result);
1773
if (!opt_no_create_info)
1775
/* Make an sql-file, if path was given iow. option -T was given */
1776
char buff[20+FN_REFLEN];
1777
uint keynr,primary_key;
1778
snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1779
if (drizzle_query_with_error_report(drizzle, &result, buff))
1781
if (drizzle_errno(drizzle) == ER_WRONG_OBJECT)
1784
fputs("\t\t<options Comment=\"view\" />\n", sql_file);
1787
fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
1788
my_progname, result_table, drizzle_error(drizzle));
1790
my_fclose(sql_file, MYF(MY_WME));
1794
/* Find first which key is primary key */
1796
primary_key=INT_MAX;
1797
while ((row= drizzle_fetch_row(result)))
1799
if (atoi(row[3]) == 1)
1802
#ifdef FORCE_PRIMARY_KEY
1803
if (atoi(row[1]) == 0 && primary_key == INT_MAX)
1806
if (!strcmp(row[2],"PRIMARY"))
1813
drizzle_data_seek(result,0);
1815
while ((row= drizzle_fetch_row(result)))
1819
print_xml_row(sql_file, "key", result, &row);
1823
if (atoi(row[3]) == 1)
1826
putc(')', sql_file);
1827
if (atoi(row[1])) /* Test if duplicate key */
1828
/* Duplicate allowed */
1829
fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0));
1830
else if (keynr == primary_key)
1831
fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
1833
fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
1837
putc(',', sql_file);
1838
fputs(quote_name(row[4], name_buff, 0), sql_file);
1840
fprintf(sql_file, " (%s)",row[7]); /* Sub key */
1843
drizzle_free_result(result);
1847
putc(')', sql_file);
1848
fputs("\n)",sql_file);
1852
/* Get DRIZZLE specific create options */
1855
char show_name_buff[NAME_LEN*2+2+24];
1857
/* Check memory for quote_for_like() */
1858
snprintf(buff, sizeof(buff), "show table status like %s",
1859
quote_for_like(table, show_name_buff));
1861
if (drizzle_query_with_error_report(drizzle, &result, buff))
1863
if (drizzle_errno(drizzle) != ER_PARSE_ERROR)
1864
{ /* If old DRIZZLE version */
1865
verbose_msg("-- Warning: Couldn't get status information for " \
1866
"table %s (%s)\n", result_table,drizzle_error(drizzle));
1869
else if (!(row= drizzle_fetch_row(result)))
1872
"Error: Couldn't read status information for table %s (%s)\n",
1873
result_table,drizzle_error(drizzle));
1878
print_xml_row(sql_file, "options", result, &row);
1881
fputs("/*!",sql_file);
1882
print_value(sql_file,result,row,"engine=","Engine",0);
1883
print_value(sql_file,result,row,"","Create_options",0);
1884
print_value(sql_file,result,row,"comment=","Comment",1);
1885
fputs(" */",sql_file);
1889
drizzle_free_result(result); /* Is always safe to free */
1893
fputs(";\n", sql_file);
1895
fputs("\t</table_structure>\n", sql_file);
1899
if (complete_insert)
1901
insert_pat.append(") VALUES ");
1902
if (!extended_insert)
1903
insert_pat.append("(");
1905
if (sql_file != md_result_file)
1907
fputs("\n", sql_file);
1908
write_footer(sql_file);
1909
my_fclose(sql_file, MYF(MY_WME));
1911
return((uint) num_fields);
1912
} /* get_table_structure */
1914
static void add_load_option(string &str, const char *option,
1915
const char *option_value)
1919
/* Null value means we don't add this option. */
1925
if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
1927
/* It's a hex constant, don't escape */
1928
str.append(option_value);
1932
/* char constant; escape */
1933
field_escape(str, option_value);
1939
Allow the user to specify field terminator strings like:
1940
"'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
1941
This is done by doubling ' and add a end -\ if needed to avoid
1942
syntax errors from the SQL parser.
1945
static void field_escape(string &in, const char *from)
1947
uint end_backslashes= 0;
1956
end_backslashes^=1; /* find odd number of backslashes */
1959
if (*from == '\'' && !end_backslashes)
1961
/* We want a duplicate of "'" for DRIZZLE */
1968
/* Add missing backslashes if user has specified odd number of backs.*/
1969
if (end_backslashes)
1982
dump_table saves database contents as a series of INSERT statements.
1993
static void dump_table(char *table, char *db)
1996
char buf[200], table_buff[NAME_LEN+3];
1997
string query_string;
1998
char table_type[NAME_LEN];
1999
char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
2001
uint32_t rownr, row_break, total_length, init_length;
2004
DRIZZLE_FIELD *field;
2009
Make sure you get the create table info before the following check for
2010
--no-data flag below. Otherwise, the create table info won't be printed.
2012
num_fields= get_table_structure(table, db, table_type, &ignore_flag);
2015
The "table" could be a view. If so, we don't do anything here.
2017
if (strcmp(table_type, "VIEW") == 0)
2020
/* Check --no-data flag */
2023
verbose_msg("-- Skipping dump data for table '%s', --no-data was used\n",
2029
If the table type is a merge table or any type that has to be
2030
_completely_ ignored and no data dumped
2032
if (ignore_flag & IGNORE_DATA)
2034
verbose_msg("-- Warning: Skipping data for table '%s' because " \
2035
"it's of type %s\n", table, table_type);
2038
/* Check that there are any fields in the table */
2039
if (num_fields == 0)
2041
verbose_msg("-- Skipping dump data for table '%s', it has no fields\n",
2047
Check --skip-events flag: it is not enough to skip creation of events
2048
discarding SHOW CREATE EVENT statements generation. The myslq.event
2049
table data should be skipped too.
2051
if (!opt_events && !my_strcasecmp(&my_charset_utf8_general_ci, db, "mysql") &&
2052
!my_strcasecmp(&my_charset_utf8_general_ci, table, "event"))
2054
verbose_msg("-- Skipping data table mysql.event, --skip-events was used\n");
2058
result_table= quote_name(table,table_buff, 1);
2059
opt_quoted_table= quote_name(table, table_buff2, 0);
2061
verbose_msg("-- Sending SELECT query...\n");
2063
query_string.clear();
2064
query_string.reserve(1024);
2068
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
2071
Convert the path to native os format
2072
and resolve to the full filepath.
2074
convert_dirname(tmp_path,path,NULL);
2075
my_load_path(tmp_path, tmp_path, NULL);
2076
fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
2078
/* Must delete the file that 'INTO OUTFILE' will write to */
2079
my_delete(filename, MYF(0));
2081
/* convert to a unix path name to stick into the query */
2082
to_unix_path(filename);
2084
/* now build the query string */
2086
query_string.append( "SELECT * INTO OUTFILE '");
2087
query_string.append( filename);
2088
query_string.append( "'");
2090
if (fields_terminated || enclosed || opt_enclosed || escaped)
2091
query_string.append( " FIELDS");
2093
add_load_option(query_string, " TERMINATED BY ", fields_terminated);
2094
add_load_option(query_string, " ENCLOSED BY ", enclosed);
2095
add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
2096
add_load_option(query_string, " ESCAPED BY ", escaped);
2097
add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
2099
query_string.append( " FROM ");
2100
query_string.append( result_table);
2104
query_string.append( " WHERE ");
2105
query_string.append( where);
2110
query_string.append( " ORDER BY ");
2111
query_string.append( order_by);
2114
if (drizzle_real_query(drizzle, query_string.c_str(), query_string.length()))
2116
DB_error(drizzle, "when executing 'SELECT INTO OUTFILE'");
2122
if (!opt_xml && opt_comments)
2124
fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
2126
check_io(md_result_file);
2129
query_string.append( "SELECT * FROM ");
2130
query_string.append( result_table);
2134
if (!opt_xml && opt_comments)
2136
fprintf(md_result_file, "-- WHERE: %s\n", where);
2137
check_io(md_result_file);
2140
query_string.append( " WHERE ");
2141
query_string.append( where);
2145
if (!opt_xml && opt_comments)
2147
fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
2148
check_io(md_result_file);
2150
query_string.append( " ORDER BY ");
2151
query_string.append( order_by);
2154
if (!opt_xml && !opt_compact)
2156
fputs("\n", md_result_file);
2157
check_io(md_result_file);
2159
if (drizzle_query_with_error_report(drizzle, 0, query_string.c_str()))
2161
DB_error(drizzle, "when retrieving data from server");
2165
res=drizzle_use_result(drizzle);
2167
res=drizzle_store_result(drizzle);
2170
DB_error(drizzle, "when retrieving data from server");
2174
verbose_msg("-- Retrieving rows...\n");
2175
if (drizzle_num_fields(res) != num_fields)
2177
fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n",
2178
my_progname, result_table);
2179
error= EX_CONSCHECK;
2185
fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
2186
check_io(md_result_file);
2188
/* Moved disable keys to after lock per bug 15977 */
2189
if (opt_disable_keys)
2191
fprintf(md_result_file, "/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
2193
check_io(md_result_file);
2196
total_length= opt_net_buffer_length; /* Force row break */
2199
init_length=(uint) insert_pat.length()+4;
2201
print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
2205
fprintf(md_result_file, "set autocommit=0;\n");
2206
check_io(md_result_file);
2209
while ((row= drizzle_fetch_row(res)))
2212
uint32_t *lengths= drizzle_fetch_lengths(res);
2214
if (!extended_insert && !opt_xml)
2216
fputs(insert_pat.c_str(),md_result_file);
2217
check_io(md_result_file);
2219
drizzle_field_seek(res,0);
2223
fputs("\t<row>\n", md_result_file);
2224
check_io(md_result_file);
2227
for (i= 0; i < drizzle_num_fields(res); i++)
2230
uint32_t length= lengths[i];
2232
if (!(field= drizzle_fetch_field(res)))
2234
"Not enough fields from table %s! Aborting.\n",
2238
63 is my_charset_bin. If charsetnr is not 63,
2239
we have not a BLOB but a TEXT column.
2240
we'll dump in hex only BLOB columns.
2242
is_blob= (opt_hex_blob && field->charsetnr == 63 &&
2243
(field->type == DRIZZLE_TYPE_VARCHAR ||
2244
field->type == DRIZZLE_TYPE_BLOB)) ? 1 : 0;
2245
if (extended_insert && !opt_xml)
2250
extended_row.append(",");
2256
if (!(field->type & NUM_FLAG))
2259
"length * 2 + 2" is OK for both HEX and non-HEX modes:
2260
- In HEX mode we need exactly 2 bytes per character
2261
plus 2 bytes for '0x' prefix.
2262
- In non-HEX mode we need up to 2 bytes per character,
2263
plus 2 bytes for leading and trailing '\'' characters.
2264
Also we need to reserve 1 byte for terminating '\0'.
2266
char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
2267
memset(tmp_str, '\0', length * 2 + 2 + 1);
2268
if (opt_hex_blob && is_blob)
2270
extended_row.append("0x");
2271
drizzle_hex_string(tmp_str, row[i], length);
2272
extended_row.append(tmp_str);
2276
extended_row.append("'");
2277
drizzle_escape_string(tmp_str,
2279
extended_row.append(tmp_str);
2280
extended_row.append("'");
2286
/* change any strings ("inf", "-inf", "nan") into NULL */
2288
if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
2289
my_isalpha(charset_info, ptr[1])))
2290
extended_row.append( "NULL");
2293
extended_row.append( ptr);
2298
extended_row.append("''");
2301
extended_row.append("NULL");
2307
fputc(',', md_result_file);
2308
check_io(md_result_file);
2312
if (!(field->type & NUM_FLAG))
2316
if (opt_hex_blob && is_blob && length)
2318
/* Define xsi:type="xs:hexBinary" for hex encoded data */
2319
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2320
field->name, "xsi:type=", "xs:hexBinary", NULL);
2321
print_blob_as_hex(md_result_file, row[i], length);
2325
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2327
print_quoted_xml(md_result_file, row[i], length);
2329
fputs("</field>\n", md_result_file);
2331
else if (opt_hex_blob && is_blob && length)
2333
fputs("0x", md_result_file);
2334
print_blob_as_hex(md_result_file, row[i], length);
2337
unescape(md_result_file, row[i], length);
2341
/* change any strings ("inf", "-inf", "nan") into NULL */
2345
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2347
fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
2349
fputs("</field>\n", md_result_file);
2351
else if (my_isalpha(charset_info, *ptr) ||
2352
(*ptr == '-' && my_isalpha(charset_info, ptr[1])))
2353
fputs("NULL", md_result_file);
2355
fputs(ptr, md_result_file);
2360
/* The field value is NULL */
2362
fputs("NULL", md_result_file);
2364
print_xml_null_tag(md_result_file, "\t\t", "field name=",
2367
check_io(md_result_file);
2373
fputs("\t</row>\n", md_result_file);
2374
check_io(md_result_file);
2377
if (extended_insert)
2379
uint32_t row_length;
2380
extended_row.append(")");
2381
row_length= 2 + extended_row.length();
2382
if (total_length + row_length < opt_net_buffer_length)
2384
total_length+= row_length;
2385
fputc(',',md_result_file); /* Always row break */
2386
fputs(extended_row.c_str(),md_result_file);
2391
fputs(";\n", md_result_file);
2392
row_break=1; /* This is first row */
2394
fputs(insert_pat.c_str(),md_result_file);
2395
fputs(extended_row.c_str(),md_result_file);
2396
total_length= row_length+init_length;
2398
check_io(md_result_file);
2402
fputs(");\n", md_result_file);
2403
check_io(md_result_file);
2407
/* XML - close table tag and supress regular output */
2409
fputs("\t</table_data>\n", md_result_file);
2410
else if (extended_insert && row_break)
2411
fputs(";\n", md_result_file); /* If not empty table */
2412
fflush(md_result_file);
2413
check_io(md_result_file);
2414
if (drizzle_errno(drizzle))
2416
snprintf(buf, sizeof(buf),
2417
"%s: Error %d: %s when dumping table %s at row: %d\n",
2419
drizzle_errno(drizzle),
2420
drizzle_error(drizzle),
2424
error= EX_CONSCHECK;
2428
/* Moved enable keys to before unlock per bug 15977 */
2429
if (opt_disable_keys)
2431
fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
2433
check_io(md_result_file);
2437
fputs("UNLOCK TABLES;\n", md_result_file);
2438
check_io(md_result_file);
2442
fprintf(md_result_file, "commit;\n");
2443
check_io(md_result_file);
2445
drizzle_free_result(res);
2455
static char *getTableName(int reset)
2457
static DRIZZLE_RES *res= NULL;
2462
if (!(res= drizzle_list_tables(drizzle,NULL)))
2465
if ((row= drizzle_fetch_row(res)))
2466
return((char*) row[0]);
2469
drizzle_data_seek(res,0); /* We want to read again */
2472
drizzle_free_result(res);
2476
} /* getTableName */
342
2479
static int dump_all_databases()
345
drizzle_result_st *tableres;
2482
DRIZZLE_RES *tableres;
348
DrizzleDumpDatabase *database;
351
std::cerr << _("-- Retrieving database structures...") << std::endl;
353
/* Blocking the MySQL privilege tables too because we can't import them due to bug#646187 */
354
if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
355
query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')";
357
query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM DATA_DICTIONARY.SCHEMAS WHERE SCHEMA_NAME NOT IN ('information_schema','data_dictionary')";
359
tableres= db_connection->query(query);
360
while ((row= drizzle_row_next(tableres)))
2485
if (drizzle_query_with_error_report(drizzle, &tableres, "SHOW DATABASES"))
2487
while ((row= drizzle_fetch_row(tableres)))
362
std::string database_name(row[0]);
363
if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
364
database= new DrizzleDumpDatabaseMySQL(database_name, db_connection);
366
database= new DrizzleDumpDatabaseDrizzle(database_name, db_connection);
368
database->setCollate(row[1]);
369
database_store.push_back(database);
2489
if (dump_all_tables_in_db(row[0]))
371
db_connection->freeResult(tableres);
374
2494
/* dump_all_databases */
377
static int dump_databases(const vector<string> &db_names)
2497
static int dump_databases(char **db_names)
381
DrizzleDumpDatabase *database;
383
for (vector<string>::const_iterator it= db_names.begin(); it != db_names.end(); ++it)
2503
for (db= db_names ; *db ; db++)
386
if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
387
database= new DrizzleDumpDatabaseMySQL(temp, db_connection);
389
database= new DrizzleDumpDatabaseDrizzle(temp, db_connection);
390
database_store.push_back(database);
2505
if (dump_all_tables_in_db(*db))
393
2509
} /* dump_databases */
395
static int dump_selected_tables(const string &db, const vector<string> &table_names)
397
DrizzleDumpDatabase *database;
399
if (db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND)
400
database= new DrizzleDumpDatabaseMySQL(db, db_connection);
402
database= new DrizzleDumpDatabaseDrizzle(db, db_connection);
404
if (not database->populateTables(table_names))
407
if (not ignore_errors)
408
maybe_exit(EX_DRIZZLEERR);
411
database_store.push_back(database);
2513
Table Specific database initalization.
2517
qdatabase quoted name of the database
2524
int init_dumping_tables(char *qdatabase)
2532
DRIZZLE_RES *dbinfo;
2534
snprintf(qbuf, sizeof(qbuf),
2535
"SHOW CREATE DATABASE IF NOT EXISTS %s",
2538
if (drizzle_query(drizzle, qbuf) || !(dbinfo = drizzle_store_result(drizzle)))
2540
/* Old server version, dump generic CREATE DATABASE */
2541
if (opt_drop_database)
2542
fprintf(md_result_file,
2543
"\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
2545
fprintf(md_result_file,
2546
"\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
2551
if (opt_drop_database)
2552
fprintf(md_result_file,
2553
"\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
2555
row = drizzle_fetch_row(dbinfo);
2558
fprintf(md_result_file,"\n%s;\n",row[1]);
2560
drizzle_free_result(dbinfo);
2564
} /* init_dumping_tables */
2567
static int init_dumping(char *database, int init_func(char*))
2569
if (drizzle_get_server_version(drizzle) >= 50003 &&
2570
!my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
2573
if (drizzle_select_db(drizzle, database))
2575
DB_error(drizzle, "when selecting the database");
2576
return 1; /* If --force */
2578
if (!path && !opt_xml)
2580
if (opt_databases || opt_alldbs)
2583
length of table name * 2 (if name contains quotes), 2 quotes and 0
2585
char quoted_database_buf[NAME_LEN*2+3];
2586
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
2589
fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
2590
check_io(md_result_file);
2593
/* Call the view or table specific function */
2594
init_func(qdatabase);
2596
fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
2597
check_io(md_result_file);
2600
if (extended_insert)
2601
extended_row.clear();
2603
} /* init_dumping */
2606
/* Return 1 if we should copy the table */
2608
static bool include_table(const unsigned char *hash_key, size_t len)
2610
return !hash_search(&ignore_table, hash_key, len);
2614
static int dump_all_tables_in_db(char *database)
2618
char table_buff[NAME_LEN*2+3];
2619
char hash_key[2*NAME_LEN+2]; /* "db.tablename" */
2621
int using_mysql_db= my_strcasecmp(&my_charset_utf8_general_ci, database, "mysql");
2624
afterdot= my_stpcpy(hash_key, database);
2627
if (init_dumping(database, init_dumping_tables))
2630
print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NULL);
2634
query= "LOCK TABLES ";
2635
for (numrows= 0 ; (table= getTableName(1)) ; )
2637
char *end= my_stpcpy(afterdot, table);
2638
if (include_table((unsigned char*) hash_key,end - hash_key))
2641
query.append( quote_name(table, table_buff, 1));
2642
query.append( " READ /*!32311 LOCAL */,");
2645
if (numrows && drizzle_real_query(drizzle, query.c_str(), query.length()-1))
2646
DB_error(drizzle, "when using LOCK TABLES");
2647
/* We shall continue here, if --force was given */
2652
if (drizzle_refresh(drizzle, REFRESH_LOG))
2653
DB_error(drizzle, "when doing refresh");
2654
/* We shall continue here, if --force was given */
2656
while ((table= getTableName(0)))
2658
char *end= my_stpcpy(afterdot, table);
2659
if (include_table((unsigned char*) hash_key, end - hash_key))
2661
dump_table(table,database);
2668
fputs("</database>\n", md_result_file);
2669
check_io(md_result_file);
2672
drizzle_query_with_error_report(drizzle, 0, "UNLOCK TABLES");
2673
if (flush_privileges && using_mysql_db == 0)
2675
fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n");
2676
fprintf(md_result_file,"\n/*! FLUSH PRIVILEGES */;\n");
2679
} /* dump_all_tables_in_db */
2683
get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
2684
table name from the server for the table name given on the command line.
2685
we do this because the table name given on the command line may be a
2686
different case (e.g. T1 vs t1)
2689
pointer to the table name
2693
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
2696
DRIZZLE_RES *table_res;
2698
char query[50 + 2*NAME_LEN];
2699
char show_name_buff[FN_REFLEN];
2702
/* Check memory for quote_for_like() */
2703
assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
2704
snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
2705
quote_for_like(old_table_name, show_name_buff));
2707
if (drizzle_query_with_error_report(drizzle, 0, query))
2710
if ((table_res= drizzle_store_result(drizzle)))
2712
uint64_t num_rows= drizzle_num_rows(table_res);
2718
TODO: Return all matching rows
2720
row= drizzle_fetch_row(table_res);
2721
lengths= drizzle_fetch_lengths(table_res);
2722
name= strmake_root(root, row[0], lengths[0]);
2724
drizzle_free_result(table_res);
2730
static int dump_selected_tables(char *db, char **table_names, int tables)
2732
char table_buff[NAME_LEN*2+3];
2733
string lock_tables_query;
2735
char **dump_tables, **pos, **end;
2738
if (init_dumping(db, init_dumping_tables))
2741
init_alloc_root(&root, 8192, 0);
2742
if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
2743
die(EX_EOM, "alloc_root failure.");
2745
lock_tables_query= "LOCK TABLES ";
2746
for (; tables > 0 ; tables-- , table_names++)
2748
/* the table name passed on commandline may be wrong case */
2749
if ((*pos= get_actual_table_name(*table_names, &root)))
2751
/* Add found table name to lock_tables_query */
2754
lock_tables_query.append( quote_name(*pos, table_buff, 1));
2755
lock_tables_query.append( " READ /*!32311 LOCAL */,");
2763
free_root(&root, MYF(0));
2765
maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
2766
/* We shall countinue here, if --force was given */
2773
if (drizzle_real_query(drizzle, lock_tables_query.c_str(),
2774
lock_tables_query.length()-1))
2778
free_root(&root, MYF(0));
2780
DB_error(drizzle, "when doing LOCK TABLES");
2781
/* We shall countinue here, if --force was given */
2786
if (drizzle_refresh(drizzle, REFRESH_LOG))
2789
free_root(&root, MYF(0));
2790
DB_error(drizzle, "when doing refresh");
2792
/* We shall countinue here, if --force was given */
2795
print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NULL);
2797
/* Dump each selected table */
2798
for (pos= dump_tables; pos < end; pos++)
2799
dump_table(*pos, db);
2801
free_root(&root, MYF(0));
2806
fputs("</database>\n", md_result_file);
2807
check_io(md_result_file);
2810
drizzle_query_with_error_report(drizzle, 0, "UNLOCK TABLES");
414
2812
} /* dump_selected_tables */
416
static int do_flush_tables_read_lock()
2815
static int do_show_master_status(DRIZZLE *drizzle_con)
2818
DRIZZLE_RES *master;
2819
const char *comment_prefix=
2820
(opt_master_data == DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
2821
if (drizzle_query_with_error_report(drizzle_con, &master, "SHOW MASTER STATUS"))
2827
row= drizzle_fetch_row(master);
2828
if (row && row[0] && row[1])
2830
/* SHOW MASTER STATUS reports file and position */
2832
fprintf(md_result_file,
2833
"\n--\n-- Position to start replication or point-in-time "
2834
"recovery from\n--\n\n");
2835
fprintf(md_result_file,
2836
"%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
2837
comment_prefix, row[0], row[1]);
2838
check_io(md_result_file);
2840
else if (!ignore_errors)
2842
/* SHOW MASTER STATUS reports nothing and --force is not enabled */
2843
my_printf_error(0, "Error: Binlogging on server not active",
2845
drizzle_free_result(master);
2846
maybe_exit(EX_DRIZZLEERR);
2849
drizzle_free_result(master);
2854
static int do_stop_slave_sql(DRIZZLE *drizzle_con)
2857
/* We need to check if the slave sql is running in the first place */
2858
if (drizzle_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
2862
DRIZZLE_ROW row= drizzle_fetch_row(slave);
2865
/* if SLAVE SQL is not running, we don't stop it */
2866
if (!strcmp(row[11],"No"))
2868
drizzle_free_result(slave);
2869
/* Silently assume that they don't have the slave running */
2874
drizzle_free_result(slave);
2876
/* now, stop slave if running */
2877
if (drizzle_query_with_error_report(drizzle_con, 0, "STOP SLAVE SQL_THREAD"))
2883
static int add_stop_slave(void)
2886
fprintf(md_result_file,
2887
"\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
2888
fprintf(md_result_file, "STOP SLAVE;\n");
2892
static int add_slave_statements(void)
2895
fprintf(md_result_file,
2896
"\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
2897
fprintf(md_result_file, "START SLAVE;\n");
2901
static int do_show_slave_status(DRIZZLE *drizzle_con)
2904
const char *comment_prefix=
2905
(opt_slave_data == DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
2906
if (drizzle_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
2910
/* SHOW SLAVE STATUS reports nothing and --force is not enabled */
2911
my_printf_error(0, "Error: Slave not set up", MYF(0));
2917
DRIZZLE_ROW row= drizzle_fetch_row(slave);
2918
if (row && row[9] && row[21])
2920
/* SHOW MASTER STATUS reports file and position */
2922
fprintf(md_result_file,
2923
"\n--\n-- Position to start replication or point-in-time "
2924
"recovery from (the master of this slave)\n--\n\n");
2926
fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
2928
if (opt_include_master_host_port)
2931
fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
2933
fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
2935
fprintf(md_result_file,
2936
"MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
2938
check_io(md_result_file);
2940
drizzle_free_result(slave);
2945
static int do_start_slave_sql(DRIZZLE *drizzle_con)
2948
/* We need to check if the slave sql is stopped in the first place */
2949
if (drizzle_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
2953
DRIZZLE_ROW row= drizzle_fetch_row(slave);
2956
/* if SLAVE SQL is not running, we don't start it */
2957
if (!strcmp(row[11],"Yes"))
2959
drizzle_free_result(slave);
2960
/* Silently assume that they don't have the slave running */
2965
drizzle_free_result(slave);
2967
/* now, start slave if stopped */
2968
if (drizzle_query_with_error_report(drizzle_con, 0, "START SLAVE"))
2970
my_printf_error(0, "Error: Unable to start slave", MYF(0));
2978
static int do_flush_tables_read_lock(DRIZZLE *drizzle_con)
419
2981
We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
420
2982
will wait but will not stall the whole mysqld, and when the long update is
421
2983
done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
422
FLUSH TABLES is to lower the probability of a stage where both drizzled
2984
FLUSH TABLES is to lower the probability of a stage where both mysqldump
423
2985
and most client connections are stalled. Of course, if a second long
424
2986
update starts between the two FLUSHes, we have that bad stall.
427
db_connection->queryNoResult("FLUSH TABLES");
428
db_connection->queryNoResult("FLUSH TABLES WITH READ LOCK");
433
static int do_unlock_tables()
435
db_connection->queryNoResult("UNLOCK TABLES");
439
static int start_transaction()
441
db_connection->queryNoResult("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ");
442
db_connection->queryNoResult("START TRANSACTION WITH CONSISTENT SNAPSHOT");
2989
( drizzle_query_with_error_report(drizzle_con, 0, "FLUSH TABLES") ||
2990
drizzle_query_with_error_report(drizzle_con, 0,
2991
"FLUSH TABLES WITH READ LOCK") );
2995
static int do_unlock_tables(DRIZZLE *drizzle_con)
2997
return drizzle_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES");
3000
static int get_bin_log_name(DRIZZLE *drizzle_con,
3001
char* buff_log_name, uint buff_len)
3006
if (drizzle_query(drizzle_con, "SHOW MASTER STATUS") ||
3007
!(res= drizzle_store_result(drizzle)))
3010
if (!(row= drizzle_fetch_row(res)))
3012
drizzle_free_result(res);
3016
Only one row is returned, and the first column is the name of the
3019
strmake(buff_log_name, row[0], buff_len - 1);
3021
drizzle_free_result(res);
3025
static int purge_bin_logs_to(DRIZZLE *drizzle_con, char* log_name)
3028
string str= "PURGE BINARY LOGS TO '";
3029
str.append(log_name);
3031
err = drizzle_query_with_error_report(drizzle_con, 0, str.c_str());
3036
static int start_transaction(DRIZZLE *drizzle_con)
3039
We use BEGIN for old servers. --single-transaction --master-data will fail
3040
on old servers, but that's ok as it was already silently broken (it didn't
3041
do a consistent read, so better tell people frankly, with the error).
3043
We want the first consistent read to be used for all tables to dump so we
3044
need the REPEATABLE READ level (not anything lower, for example READ
3045
COMMITTED would give one new consistent read per dumped table).
3047
if ((drizzle_get_server_version(drizzle_con) < 40100) && opt_master_data)
3049
fprintf(stderr, "-- %s: the combination of --single-transaction and "
3050
"--master-data requires a DRIZZLE server version of at least 4.1 "
3051
"(current server's version is %s). %s\n",
3052
ignore_errors ? "Warning" : "Error",
3053
drizzle_con->server_version ? drizzle_con->server_version : "unknown",
3054
ignore_errors ? "Continuing due to --force, backup may not be consistent across all tables!" : "Aborting.");
3056
exit(EX_DRIZZLEERR);
3059
return (drizzle_query_with_error_report(drizzle_con, 0,
3060
"SET SESSION TRANSACTION ISOLATION "
3061
"LEVEL REPEATABLE READ") ||
3062
drizzle_query_with_error_report(drizzle_con, 0,
3063
"START TRANSACTION "
3064
"/*!40100 WITH CONSISTENT SNAPSHOT */"));
3068
static uint32_t find_set(TYPELIB *lib, const char *x, uint length,
3069
char **err_pos, uint *err_len)
3071
const char *end= x + length;
3076
*err_pos= 0; /* No error yet */
3077
while (end > x && my_isspace(charset_info, end[-1]))
3083
const char *start= x;
3086
const char *pos= start;
3089
for (; pos != end && *pos != ','; pos++) ;
3090
var_len= (uint32_t) (pos - start);
3091
strmake(buff, start, min((uint32_t)sizeof(buff), var_len));
3092
find= find_type(buff, lib, var_len);
3095
*err_pos= (char*) start;
3099
found|= ((int64_t) 1 << (find - 1));
3109
/* Print a value with a prefix on file */
3110
static void print_value(FILE *file, DRIZZLE_RES *result, DRIZZLE_ROW row,
3111
const char *prefix, const char *name,
3114
DRIZZLE_FIELD *field;
3115
drizzle_field_seek(result, 0);
3117
for ( ; (field= drizzle_fetch_field(result)) ; row++)
3119
if (!strcmp(field->name,name))
3121
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
3124
fputs(prefix, file);
3126
unescape(file,row[0],(uint) strlen(row[0]));
3128
fputs(row[0], file);
3134
return; /* This shouldn't happen */
3141
Check if we the table is one of the table types that should be ignored:
3142
MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
3143
If the table should be altogether ignored, it returns a true, false if it
3144
should not be ignored. If the user has selected to use INSERT DELAYED, it
3145
sets the value of the bool pointer supports_delayed_inserts to 0 if not
3146
supported, 1 if it is supported.
3150
check_if_ignore_table()
3151
table_name Table name to check
3152
table_type Type of table
3155
drizzle Drizzle connection
3156
verbose Write warning messages
3159
char (bit value) See IGNORE_ values at top
3162
char check_if_ignore_table(const char *table_name, char *table_type)
3164
char result= IGNORE_NONE;
3165
char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
3166
DRIZZLE_RES *res= NULL;
3170
/* Check memory for quote_for_like() */
3171
assert(2*sizeof(table_name) < sizeof(show_name_buff));
3172
snprintf(buff, sizeof(buff), "show table status like %s",
3173
quote_for_like(table_name, show_name_buff));
3174
if (drizzle_query_with_error_report(drizzle, &res, buff))
3176
if (drizzle_errno(drizzle) != ER_PARSE_ERROR)
3177
{ /* If old DRIZZLE version */
3178
verbose_msg("-- Warning: Couldn't get status information for "
3179
"table %s (%s)\n", table_name, drizzle_error(drizzle));
3180
return(result); /* assume table is ok */
3183
if (!(row= drizzle_fetch_row(res)))
3186
"Error: Couldn't read status information for table %s (%s)\n",
3187
table_name, drizzle_error(drizzle));
3188
drizzle_free_result(res);
3189
return(result); /* assume table is ok */
3192
strmake(table_type, "VIEW", NAME_LEN-1);
3196
If the table type matches any of these, we do support delayed inserts.
3197
Note: we do not want to skip dumping this table if if is not one of
3198
these types, but we do want to use delayed inserts in the dump if
3199
the table type is _NOT_ one of these types
3201
strmake(table_type, row[1], NAME_LEN-1);
3204
if (strcmp(table_type,"MyISAM") &&
3205
strcmp(table_type,"ISAM") &&
3206
strcmp(table_type,"ARCHIVE") &&
3207
strcmp(table_type,"HEAP") &&
3208
strcmp(table_type,"MEMORY"))
3209
result= IGNORE_INSERT_DELAYED;
3213
If these two types, we do want to skip dumping the table
3216
(!my_strcasecmp(&my_charset_utf8_general_ci, table_type, "MRG_MyISAM") ||
3217
!strcmp(table_type,"MRG_ISAM")))
3218
result= IGNORE_DATA;
3220
drizzle_free_result(res);
3226
Get string of comma-separated primary key field names
3229
char *primary_key_fields(const char *table_name)
3230
RETURNS pointer to allocated buffer (must be freed by caller)
3231
table_name quoted table name
3234
Use SHOW KEYS FROM table_name, allocate a buffer to hold the
3235
field names, and then build that string and return the pointer
3238
Returns NULL if there is no PRIMARY or UNIQUE key on the table,
3239
or if there is some failure. It is better to continue to dump
3240
the table unsorted, rather than exit without dumping the data.
3243
static char *primary_key_fields(const char *table_name)
3245
DRIZZLE_RES *res= NULL;
3247
/* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
3248
char show_keys_buff[15 + NAME_LEN * 2 + 3];
3249
uint result_length= 0;
3251
char buff[NAME_LEN * 2 + 3];
3254
snprintf(show_keys_buff, sizeof(show_keys_buff),
3255
"SHOW KEYS FROM %s", table_name);
3256
if (drizzle_query(drizzle, show_keys_buff) ||
3257
!(res= drizzle_store_result(drizzle)))
3259
fprintf(stderr, "Warning: Couldn't read keys from table %s;"
3260
" records are NOT sorted (%s)\n",
3261
table_name, drizzle_error(drizzle));
3262
/* Don't exit, because it's better to print out unsorted records */
3267
* Figure out the length of the ORDER BY clause result.
3268
* Note that SHOW KEYS is ordered: a PRIMARY key is always the first
3269
* row, and UNIQUE keys come before others. So we only need to check
3270
* the first key, not all keys.
3272
if ((row= drizzle_fetch_row(res)) && atoi(row[1]) == 0)
3277
quoted_field= quote_name(row[4], buff, 0);
3278
result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
3279
} while ((row= drizzle_fetch_row(res)) && atoi(row[3]) > 1);
3282
/* Build the ORDER BY clause result */
3286
/* result (terminating \0 is already in result_length) */
3287
result= (char *)my_malloc(result_length + 10, MYF(MY_WME));
3290
fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n");
3293
drizzle_data_seek(res, 0);
3294
row= drizzle_fetch_row(res);
3295
quoted_field= quote_name(row[4], buff, 0);
3296
end= my_stpcpy(result, quoted_field);
3297
while ((row= drizzle_fetch_row(res)) && atoi(row[3]) > 1)
3299
quoted_field= quote_name(row[4], buff, 0);
3300
end= strxmov(end, ",", quoted_field, NULL);
3306
drizzle_free_result(res);
446
3312
int main(int argc, char **argv)
3314
char bin_log_name[FN_REFLEN];
452
#if defined(ENABLE_NLS)
453
# if defined(HAVE_LOCALE_H)
454
setlocale(LC_ALL, "");
456
bindtextdomain("drizzle7", LOCALEDIR);
457
textdomain("drizzle7");
460
po::options_description commandline_options(_("Options used only in command line"));
461
commandline_options.add_options()
462
("all-databases,A", po::value<bool>(&opt_alldbs)->default_value(false)->zero_tokens(),
463
_("Dump all the databases. This will be same as --databases with all databases selected."))
464
("flush-logs,F", po::value<bool>(&flush_logs)->default_value(false)->zero_tokens(),
465
_("Flush logs file in server before starting dump. Note that if you dump many databases at once (using the option --databases= or --all-databases), the logs will be flushed for each database dumped. The exception is when using --lock-all-tables in this case the logs will be flushed only once, corresponding 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 --flush-logs"))
466
("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
467
_("Continue even if we get an sql-error."))
468
("help,?", _("Display this help message and exit."))
469
("lock-all-tables,x", po::value<bool>(&opt_lock_all_tables)->default_value(false)->zero_tokens(),
470
_("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 off."))
471
("single-transaction", po::value<bool>(&opt_single_transaction)->default_value(false)->zero_tokens(),
472
_("Creates a consistent snapshot by dumping all tables in a single transaction. Works ONLY for tables stored in storage engines which support multiversioning (currently only InnoDB does); the dump is NOT guaranteed to be consistent for other storage engines. While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents), no other connection should use the following statements: ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not isolated from them."))
474
_("Disable --opt. Disables --add-drop-table, --add-locks, --create-options, ---extended-insert and --disable-keys."))
475
("tables", _("Overrides option --databases (-B)."))
476
("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(10000),
477
_("Number of rows before each output progress report (requires --verbose)."))
478
("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
479
_("Print info about the various stages."))
480
("version,V", _("Output version information and exit."))
481
("skip-comments", _("Turn off Comments"))
482
("skip-create", _("Turn off create-options"))
483
("skip-extended-insert", _("Turn off extended-insert"))
484
("skip-dump-date", _( "Turn off dump date at the end of the output"))
485
("no-defaults", _("Do not read from the configuration files"))
488
po::options_description dump_options(_("Options specific to the drizzle client"));
489
dump_options.add_options()
490
("add-drop-database", po::value<bool>(&opt_drop_database)->default_value(false)->zero_tokens(),
491
_("Add a 'DROP DATABASE' before each create."))
492
("skip-drop-table", _("Do not add a 'drop table' before each create."))
493
("compact", po::value<bool>(&opt_compact)->default_value(false)->zero_tokens(),
494
_("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"))
495
("databases,B", po::value<bool>(&opt_databases)->default_value(false)->zero_tokens(),
496
_("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."))
497
("skip-disable-keys,K",
498
_("'ALTER TABLE tb_name DISABLE KEYS;' and 'ALTER TABLE tb_name ENABLE KEYS;' will not be put in the output."))
499
("ignore-table", po::value<string>(),
500
_("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"))
501
("insert-ignore", po::value<bool>(&opt_ignore)->default_value(false)->zero_tokens(),
502
_("Insert rows with INSERT IGNORE."))
503
("no-autocommit", po::value<bool>(&opt_autocommit)->default_value(false)->zero_tokens(),
504
_("Wrap a table's data in START TRANSACTION/COMMIT statements."))
505
("no-create-db,n", po::value<bool>(&opt_create_db)->default_value(false)->zero_tokens(),
506
_("'CREATE DATABASE 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."))
507
("no-data,d", po::value<bool>(&opt_no_data)->default_value(false)->zero_tokens(),
508
_("No row information."))
509
("replace", po::value<bool>(&opt_replace_into)->default_value(false)->zero_tokens(),
510
_("Use REPLACE INTO instead of INSERT INTO."))
511
("destination-type", po::value<string>()->default_value("stdout"),
512
_("Where to send output to (stdout|database"))
513
("destination-host", po::value<string>(&opt_destination_host)->default_value("localhost"),
514
_("Hostname for destination db server (requires --destination-type=database)"))
515
("destination-port", po::value<uint16_t>(&opt_destination_port)->default_value(4427),
516
_("Port number for destination db server (requires --destination-type=database)"))
517
("destination-user", po::value<string>(&opt_destination_user),
518
_("User name for destination db server (resquires --destination-type=database)"))
519
("destination-password", po::value<string>(&opt_destination_password),
520
_("Password for destination db server (requires --destination-type=database)"))
521
("destination-database", po::value<string>(&opt_destination_database),
522
_("The database in the destination db server (requires --destination-type=database, not for use with --all-databases)"))
523
("my-data-is-mangled", po::value<bool>(&opt_data_is_mangled)->default_value(false)->zero_tokens(),
524
_("Do not make a UTF8 connection to MySQL, use if you have UTF8 data in a non-UTF8 table"))
527
po::options_description client_options(_("Options specific to the client"));
528
client_options.add_options()
529
("host,h", po::value<string>(¤t_host)->default_value("localhost"),
530
_("Connect to host."))
531
("password,P", po::value<string>(&password)->default_value(PASSWORD_SENTINEL),
532
_("Password to use when connecting to server. If password is not given it's solicited on the tty."))
533
("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
534
_("Port number to use for connection."))
535
("user,u", po::value<string>(¤t_user)->default_value(""),
536
_("User for login if not current user."))
537
("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
538
_("The protocol of connection (mysql or drizzle)."))
541
po::options_description hidden_options(_("Hidden Options"));
542
hidden_options.add_options()
543
("database-used", po::value<vector<string> >(), _("Used to select the database"))
544
("Table-used", po::value<vector<string> >(), _("Used to select the tables"))
547
po::options_description all_options(_("Allowed Options + Hidden Options"));
548
all_options.add(commandline_options).add(dump_options).add(client_options).add(hidden_options);
550
po::options_description long_options(_("Allowed Options"));
551
long_options.add(commandline_options).add(dump_options).add(client_options);
553
std::string system_config_dir_dump(SYSCONFDIR);
554
system_config_dir_dump.append("/drizzle/drizzledump.cnf");
556
std::string system_config_dir_client(SYSCONFDIR);
557
system_config_dir_client.append("/drizzle/client.cnf");
559
std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
561
if (user_config_dir.compare(0, 2, "~/") == 0)
564
homedir= getenv("HOME");
566
user_config_dir.replace(0, 1, homedir);
569
po::positional_options_description p;
570
p.add("database-used", 1);
571
p.add("Table-used",-1);
573
md_result_file= stdout;
575
po::variables_map vm;
577
// Disable allow_guessing
578
int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
580
po::store(po::command_line_parser(argc, argv).style(style).
581
options(all_options).positional(p).
582
extra_parser(parse_password_arg).run(), vm);
584
if (! vm.count("no-defaults"))
586
std::string user_config_dir_dump(user_config_dir);
587
user_config_dir_dump.append("/drizzle/drizzledump.cnf");
589
std::string user_config_dir_client(user_config_dir);
590
user_config_dir_client.append("/drizzle/client.cnf");
592
ifstream user_dump_ifs(user_config_dir_dump.c_str());
593
po::store(parse_config_file(user_dump_ifs, dump_options), vm);
595
ifstream user_client_ifs(user_config_dir_client.c_str());
596
po::store(parse_config_file(user_client_ifs, client_options), vm);
598
ifstream system_dump_ifs(system_config_dir_dump.c_str());
599
po::store(parse_config_file(system_dump_ifs, dump_options), vm);
601
ifstream system_client_ifs(system_config_dir_client.c_str());
602
po::store(parse_config_file(system_client_ifs, client_options), vm);
607
if ((not vm.count("database-used") && not vm.count("Table-used")
608
&& not opt_alldbs && path.empty())
609
|| (vm.count("help")) || vm.count("version"))
611
printf(_("Drizzledump %s build %s, for %s-%s (%s)\n"),
612
drizzle_version(), VERSION, HOST_VENDOR, HOST_OS, HOST_CPU);
613
if (vm.count("version"))
616
puts(_("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"));
617
puts(_("Dumps definitions and data from a Drizzle database server"));
618
printf(_("Usage: %s [OPTIONS] database [tables]\n"), progname.c_str());
619
printf(_("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n"),
621
printf(_("OR %s [OPTIONS] --all-databases [OPTIONS]\n"), progname.c_str());
622
cout << long_options;
623
if (vm.count("help"))
629
/* Inverted Booleans */
631
opt_drop= (vm.count("skip-drop-table")) ? false : true;
632
opt_comments= (vm.count("skip-comments")) ? false : true;
633
extended_insert= (vm.count("skip-extended-insert")) ? false : true;
634
opt_dump_date= (vm.count("skip-dump-date")) ? false : true;
635
opt_disable_keys= (vm.count("skip-disable-keys")) ? false : true;
636
opt_quoted= (vm.count("skip-quote-names")) ? false : true;
638
if (vm.count("protocol"))
640
std::transform(opt_protocol.begin(), opt_protocol.end(),
641
opt_protocol.begin(), ::tolower);
643
if (not opt_protocol.compare("mysql"))
644
use_drizzle_protocol=false;
645
else if (not opt_protocol.compare("drizzle"))
646
use_drizzle_protocol=true;
649
cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
654
if (vm.count("port"))
656
/* If the port number is > 65535 it is not a valid port
657
* This also helps with potential data loss casting unsigned long to a
660
if (opt_drizzle_port > 65535)
662
fprintf(stderr, _("Value supplied for port is not valid.\n"));
667
if(vm.count("password"))
669
if (!opt_password.empty())
670
opt_password.erase();
671
if (password == PASSWORD_SENTINEL)
677
opt_password= password;
691
if (vm.count("skip-opt"))
693
extended_insert= opt_drop= create_options= 0;
699
opt_comments= opt_drop= opt_disable_keys= 0;
704
extended_insert= opt_drop= create_options= 1;
708
if (vm.count("tables"))
710
opt_databases= false;
713
if (vm.count("ignore-table"))
715
if (!strchr(vm["ignore-table"].as<string>().c_str(), '.'))
717
fprintf(stderr, _("Illegal use of option --ignore-table=<database>.<table>\n"));
718
exit(EXIT_ARGUMENT_INVALID);
720
string tmpptr(vm["ignore-table"].as<string>());
721
ignore_table.insert(tmpptr);
724
if (vm.count("skip-create"))
726
opt_create_db= opt_no_create_info= create_options= false;
729
exit_code= get_options();
3316
MY_INIT("mysqldump");
3318
compatible_mode_normal_str[0]= 0;
3319
default_charset= (char *)drizzle_universal_client_charset;
3320
memset(&ignore_table, 0, sizeof(ignore_table));
3322
exit_code= get_options(&argc, &argv);
732
3325
free_resources();
733
3326
exit(exit_code);
737
db_connection = new DrizzleDumpConnection(current_host, opt_drizzle_port,
738
current_user, opt_password, use_drizzle_protocol);
740
catch (std::exception&)
742
maybe_exit(EX_DRIZZLEERR);
745
if ((db_connection->getServerType() == ServerDetect::SERVER_MYSQL_FOUND) and (not opt_data_is_mangled))
746
db_connection->queryNoResult("SET NAMES 'utf8'");
748
if (vm.count("destination-type"))
750
string tmp_destination(vm["destination-type"].as<string>());
751
if (tmp_destination.compare("database") == 0)
752
opt_destination= DESTINATION_DB;
753
else if (tmp_destination.compare("stdout") == 0)
754
opt_destination= DESTINATION_STDOUT;
756
exit(EXIT_ARGUMENT_INVALID);
760
if (path.empty() && vm.count("database-used"))
762
string database_used= *vm["database-used"].as< vector<string> >().begin();
763
write_header((char *)database_used.c_str());
766
if ((opt_lock_all_tables) && do_flush_tables_read_lock())
768
if (opt_single_transaction && start_transaction())
770
if (opt_lock_all_tables)
771
db_connection->queryNoResult("FLUSH LOGS");
772
if (opt_single_transaction && do_unlock_tables()) /* unlock but no commit! */
3331
if(!(stderror_file= freopen(log_error_file, "a+", stderr)))
3334
exit(EX_DRIZZLEERR);
3338
if (connect_to_db(current_host, current_user, opt_password))
3341
exit(EX_DRIZZLEERR);
3344
write_header(md_result_file, *argv);
3346
if (opt_slave_data && do_stop_slave_sql(drizzle))
3349
if ((opt_lock_all_tables || opt_master_data) &&
3350
do_flush_tables_read_lock(drizzle))
3352
if (opt_single_transaction && start_transaction(drizzle))
3354
if (opt_delete_master_logs)
3356
if (drizzle_refresh(drizzle, REFRESH_LOG) ||
3357
get_bin_log_name(drizzle, bin_log_name, sizeof(bin_log_name)))
3361
if (opt_lock_all_tables || opt_master_data)
3363
if (flush_logs && drizzle_refresh(drizzle, REFRESH_LOG))
3365
flush_logs= 0; /* not anymore; that would not be sensible */
3367
/* Add 'STOP SLAVE to beginning of dump */
3368
if (opt_slave_apply && add_stop_slave())
3370
if (opt_master_data && do_show_master_status(drizzle))
3372
if (opt_slave_data && do_show_slave_status(drizzle))
3374
if (opt_single_transaction && do_unlock_tables(drizzle)) /* unlock but no commit! */
777
3379
dump_all_databases();
780
if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
3381
else if (argc > 1 && !opt_databases)
782
string database_used= *vm["database-used"].as< vector<string> >().begin();
783
3383
/* Only one database and selected table(s) */
784
dump_selected_tables(database_used, vm["Table-used"].as< vector<string> >());
787
if (vm.count("Table-used") and opt_databases)
789
vector<string> database_used= vm["database-used"].as< vector<string> >();
790
vector<string> table_used= vm["Table-used"].as< vector<string> >();
792
for (vector<string>::iterator it= table_used.begin();
793
it != table_used.end();
796
database_used.insert(database_used.end(), *it);
799
dump_databases(database_used);
803
if (vm.count("database-used") && ! vm.count("Table-used"))
805
dump_databases(vm["database-used"].as< vector<string> >());
809
if (opt_destination == DESTINATION_STDOUT)
3384
dump_selected_tables(*argv, (argv + 1), (argc - 1));
3388
dump_databases(argv);
3391
/* if --dump-slave , start the slave sql thread */
3392
if (opt_slave_data && do_start_slave_sql(drizzle))
3395
/* add 'START SLAVE' to end of dump */
3396
if (opt_slave_apply && add_slave_statements())
814
3399
/* ensure dumped data flushed */
815
3400
if (md_result_file && fflush(md_result_file))