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
30
#include "client_priv.h"
32
#include <mysys/my_sys.h>
33
#include <mystrings/m_string.h>
34
#include <mystrings/m_ctype.h>
35
#include <mysys/hash.h>
37
36
#include <stdarg.h>
38
#include <boost/unordered_set.hpp>
41
#include <drizzled/gettext.h>
42
#include <drizzled/configmake.h>
43
38
#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
40
using namespace std;
52
using namespace drizzled;
53
namespace po= boost::program_options;
58
44
#define EX_DRIZZLEERR 2
45
#define EX_CONSCHECK 3
59
47
#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;
48
#define EX_ILLEGAL_TABLE 6
50
/* index into 'show fields from table' */
52
#define SHOW_FIELDNAME 0
55
#define SHOW_DEFAULT 4
58
/* Size of buffer for dump's select query */
59
#define QUERY_LENGTH 1536
61
/* ignore table flags */
62
#define IGNORE_NONE 0x00 /* no ignore */
63
#define IGNORE_DATA 0x01 /* don't dump data for this table */
64
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
66
static void add_load_option(string &str, const char *option,
67
const char *option_value);
68
static uint32_t find_set(TYPELIB *lib, const char *x, uint length,
69
char **err_pos, uint *err_len);
71
static void field_escape(string &in, const char *from);
72
static bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
73
quick= 1, extended_insert= 1,
74
lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0,
75
opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
76
opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
77
opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,
78
opt_set_charset=0, opt_dump_date=1,
79
opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
80
opt_delete_master_logs=0, tty_password=0,
81
opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
82
opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
83
opt_complete_insert= 0, opt_drop_database= 0,
85
opt_routines=0, opt_tz_utc=1,
87
opt_include_master_host_port= 0,
89
opt_alltspcs=0, opt_notspcs= 0;
90
static bool debug_info_flag= 0, debug_check_flag= 0;
91
static uint32_t opt_max_allowed_packet, opt_net_buffer_length;
92
static DRIZZLE drizzle_connection,*drizzle=0;
86
93
static string insert_pat;
87
static uint32_t opt_drizzle_port= 0;
88
static int first_error= 0;
94
static char *opt_password=0,*current_user=0,
95
*current_host=0,*path=0,*fields_terminated=0,
96
*lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
97
*where=0, *order_by=0,
98
*opt_compatible_mode_str= 0,
100
*log_error_file= NULL;
101
static char **defaults_argv= 0;
102
static char compatible_mode_normal_str[255];
103
/* Server supports character_set_results session variable? */
104
static bool server_supports_switching_charsets= true;
105
static uint32_t opt_compatible_mode= 0;
106
#define DRIZZLE_OPT_MASTER_DATA_EFFECTIVE_SQL 1
107
#define DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL 2
108
#define DRIZZLE_OPT_SLAVE_DATA_EFFECTIVE_SQL 1
109
#define DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL 2
110
static uint opt_drizzle_port= 0, opt_master_data;
111
static uint opt_slave_data;
112
static uint my_end_arg;
113
static int first_error=0;
89
114
static string extended_row;
90
115
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);
116
FILE *stderror_file=0;
118
static uint opt_protocol= DRIZZLE_PROTOCOL_TCP;
121
Constant for detection of default value of default_charset.
122
If default_charset is equal to drizzle_universal_client_charset, then
123
it is the default value which assigned at the very beginning of main().
125
static const char *drizzle_universal_client_charset=
126
DRIZZLE_UNIVERSAL_CLIENT_CHARSET;
127
static char *default_charset;
128
static const CHARSET_INFO *charset_info= &my_charset_latin1;
129
const char *default_dbug_option="d:t:o,/tmp/drizzledump.trace";
130
/* have we seen any VIEWs during table scanning? */
132
const char *compatible_mode_names[]=
134
"MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
135
"MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
139
#define MASK_ANSI_QUOTES \
141
(1<<2) | /* POSTGRESQL */\
142
(1<<3) | /* ORACLE */\
143
(1<<4) | /* MSSQL */\
145
(1<<6) | /* MAXDB */\
148
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
149
"", compatible_mode_names, NULL};
153
static struct my_option my_long_options[] =
155
{"all", 'a', "Deprecated. Use --create-options instead.",
156
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
158
{"all-databases", 'A',
159
"Dump all the databases. This will be same as --databases with all databases selected.",
160
(char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
162
{"all-tablespaces", 'Y',
163
"Dump all the tablespaces.",
164
(char**) &opt_alltspcs, (char**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
166
{"no-tablespaces", 'y',
167
"Do not dump any tablespace information.",
168
(char**) &opt_notspcs, (char**) &opt_notspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
170
{"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
171
(char**) &opt_drop_database, (char**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
173
{"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
174
(char**) &opt_drop, (char**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
176
{"add-locks", OPT_LOCKS, "Add locks around insert statements.",
177
(char**) &opt_lock, (char**) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
179
{"allow-keywords", OPT_KEYWORDS,
180
"Allow creation of column names that are keywords.", (char**) &opt_keywords,
181
(char**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
182
{"apply-slave-statements", OPT_DRIZZLEDUMP_SLAVE_APPLY,
183
"Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
184
(char**) &opt_slave_apply, (char**) &opt_slave_apply, 0, GET_BOOL, NO_ARG,
186
{"character-sets-dir", OPT_CHARSETS_DIR,
187
"Directory where character sets are.", (char**) &charsets_dir,
188
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
189
{"comments", 'i', "Write additional information.",
190
(char**) &opt_comments, (char**) &opt_comments, 0, GET_BOOL, NO_ARG,
192
{"compatible", OPT_COMPATIBLE,
193
"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.",
194
(char**) &opt_compatible_mode_str, (char**) &opt_compatible_mode_str, 0,
195
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
196
{"compact", OPT_COMPACT,
197
"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",
198
(char**) &opt_compact, (char**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
200
{"complete-insert", 'c', "Use complete insert statements.",
201
(char**) &opt_complete_insert, (char**) &opt_complete_insert, 0, GET_BOOL,
202
NO_ARG, 0, 0, 0, 0, 0, 0},
203
{"compress", 'C', "Use compression in server/client protocol.",
204
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
206
{"create-options", OPT_CREATE_OPTIONS,
207
"Include all DRIZZLE specific create options.",
208
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
211
"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.",
212
(char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
214
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
215
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
216
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
217
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
218
(char**) &debug_info_flag, (char**) &debug_info_flag,
219
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
220
{"default-character-set", OPT_DEFAULT_CHARSET,
221
"Set the default character set.", (char**) &default_charset,
222
(char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
223
{"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
224
(char**) &opt_delayed, (char**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
226
{"delete-master-logs", OPT_DELETE_MASTER_LOGS,
227
"Delete logs on master after backup. This automatically enables --master-data.",
228
(char**) &opt_delete_master_logs, (char**) &opt_delete_master_logs, 0,
229
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
230
{"disable-keys", 'K',
231
"'/*!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,
232
(char**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
233
{"dump-slave", OPT_DRIZZLEDUMP_SLAVE_DATA,
234
"This causes the binary log position and filename of the master to be "
235
"appended to the dumped data output. Setting the value to 1, will print"
236
"it as a CHANGE MASTER command in the dumped data output; if equal"
237
" to 2, that command will be prefixed with a comment symbol. "
238
"This option will turn --lock-all-tables on, unless "
239
"--single-transaction is specified too (in which case a "
240
"global read lock is only taken a short time at the beginning of the dump "
241
"- don't forget to read about --single-transaction below). In all cases "
242
"any action on logs will happen at the exact moment of the dump."
243
"Option automatically turns --lock-tables off.",
244
(char**) &opt_slave_data, (char**) &opt_slave_data, 0,
245
GET_UINT, OPT_ARG, 0, 0, DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0},
246
{"events", 'E', "Dump events.",
247
(char**) &opt_events, (char**) &opt_events, 0, GET_BOOL,
248
NO_ARG, 0, 0, 0, 0, 0, 0},
249
{"extended-insert", 'e',
250
"Allows utilization of the new, much faster INSERT syntax.",
251
(char**) &extended_insert, (char**) &extended_insert, 0, GET_BOOL, NO_ARG,
253
{"fields-terminated-by", OPT_FTB,
254
"Fields in the textfile are terminated by ...", (char**) &fields_terminated,
255
(char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
256
{"fields-enclosed-by", OPT_ENC,
257
"Fields in the importfile are enclosed by ...", (char**) &enclosed,
258
(char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
259
{"fields-optionally-enclosed-by", OPT_O_ENC,
260
"Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
261
(char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
262
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
263
(char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
264
{"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
265
(char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
267
{"flush-logs", 'F', "Flush logs file in server before starting dump. "
268
"Note that if you dump many databases at once (using the option "
269
"--databases= or --all-databases), the logs will be flushed for "
270
"each database dumped. The exception is when using --lock-all-tables "
272
"in this case the logs will be flushed only once, corresponding "
273
"to the moment all tables are locked. So if you want your dump and "
274
"the log flush to happen at the same exact moment you should use "
275
"--lock-all-tables or --master-data with --flush-logs",
276
(char**) &flush_logs, (char**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
278
{"flush-privileges", OPT_ESC, "Emit a FLUSH PRIVILEGES statement "
279
"after dumping the DRIZZLE database. This option should be used any "
280
"time the dump contains the DRIZZLE database and any other database "
281
"that depends on the data in the DRIZZLE database for proper restore. ",
282
(char**) &flush_privileges, (char**) &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
284
{"force", 'f', "Continue even if we get an sql-error.",
285
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG,
287
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
288
NO_ARG, 0, 0, 0, 0, 0, 0},
289
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
290
"VARBINARY, BLOB) in hexadecimal format.",
291
(char**) &opt_hex_blob, (char**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
292
{"host", 'h', "Connect to host.", (char**) ¤t_host,
293
(char**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
294
{"ignore-table", OPT_IGNORE_TABLE,
295
"Do not dump the specified table. To specify more than one table to ignore, "
296
"use the directive multiple times, once for each table. Each table must "
297
"be specified with both database and table names, e.g. --ignore-table=database.table",
298
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
299
{"include-master-host-port", OPT_DRIZZLEDUMP_INCLUDE_MASTER_HOST_PORT,
300
"Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' in dump produced with --dump-slave.",
301
(char**) &opt_include_master_host_port,
302
(char**) &opt_include_master_host_port,
305
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
306
(char**) &opt_ignore, (char**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
308
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
309
(char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
310
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
311
{"lock-all-tables", 'x', "Locks all tables across all databases. This "
312
"is achieved by taking a global read lock for the duration of the whole "
313
"dump. Automatically turns --single-transaction and --lock-tables off.",
314
(char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
316
{"lock-tables", 'l', "Lock all tables for read.", (char**) &lock_tables,
317
(char**) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
318
{"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.",
319
(char**) &log_error_file, (char**) &log_error_file, 0, GET_STR,
320
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
321
{"master-data", OPT_MASTER_DATA,
322
"This causes the binary log position and filename to be appended to the "
323
"output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
324
" to 2, that command will be prefixed with a comment symbol. "
325
"This option will turn --lock-all-tables on, unless "
326
"--single-transaction is specified too (in which case a "
327
"global read lock is only taken a short time at the beginning of the dump "
328
"- don't forget to read about --single-transaction below). In all cases "
329
"any action on logs will happen at the exact moment of the dump."
330
"Option automatically turns --lock-tables off.",
331
(char**) &opt_master_data, (char**) &opt_master_data, 0,
332
GET_UINT, OPT_ARG, 0, 0, DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
333
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
334
(char**) &opt_max_allowed_packet, (char**) &opt_max_allowed_packet, 0,
335
GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
336
(int64_t) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
337
{"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
338
(char**) &opt_net_buffer_length, (char**) &opt_net_buffer_length, 0,
339
GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
340
MALLOC_OVERHEAD-1024, 1024, 0},
341
{"no-autocommit", OPT_AUTOCOMMIT,
342
"Wrap tables with autocommit/commit statements.",
343
(char**) &opt_autocommit, (char**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
345
{"no-create-db", 'n',
346
"'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.}.",
347
(char**) &opt_create_db, (char**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
349
{"no-create-info", 't', "Don't write table creation info.",
350
(char**) &opt_no_create_info, (char**) &opt_no_create_info, 0, GET_BOOL,
351
NO_ARG, 0, 0, 0, 0, 0, 0},
352
{"no-data", 'd', "No row information.", (char**) &opt_no_data,
353
(char**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
354
{"no-set-names", 'N',
355
"Deprecated. Use --skip-set-charset instead.",
356
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
357
{"opt", OPT_OPTIMIZE,
358
"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.",
359
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
360
{"order-by-primary", OPT_ORDER_BY_PRIMARY,
361
"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.",
362
(char**) &opt_order_by_primary, (char**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
364
"Password to use when connecting to server. If password is not given it's solicited on the tty.",
365
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
366
{"port", 'P', "Port number to use for connection.", (char**) &opt_drizzle_port,
367
(char**) &opt_drizzle_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
369
{"quick", 'q', "Don't buffer query, dump directly to stdout.",
370
(char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
371
{"quote-names",'Q', "Quote table and column names with backticks (`).",
372
(char**) &opt_quoted, (char**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
374
{"replace", OPT_DRIZZLE_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
375
(char**) &opt_replace_into, (char**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
378
"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).",
379
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
380
{"routines", 'R', "Dump stored routines (functions and procedures).",
381
(char**) &opt_routines, (char**) &opt_routines, 0, GET_BOOL,
382
NO_ARG, 0, 0, 0, 0, 0, 0},
383
{"set-charset", OPT_SET_CHARSET,
384
"Add 'SET NAMES default_character_set' to the output.",
385
(char**) &opt_set_charset, (char**) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
387
{"set-variable", 'O',
388
"Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
389
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
391
Note that the combination --single-transaction --master-data
392
will give bullet-proof binlog position only if server >=4.1.3. That's the
393
old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug.
395
{"single-transaction", OPT_TRANSACTION,
396
"Creates a consistent snapshot by dumping all tables in a single "
397
"transaction. Works ONLY for tables stored in storage engines which "
398
"support multiversioning (currently only InnoDB does); the dump is NOT "
399
"guaranteed to be consistent for other storage engines. "
400
"While a --single-transaction dump is in process, to ensure a valid "
401
"dump file (correct table contents and binary log position), no other "
402
"connection should use the following statements: ALTER TABLE, DROP "
403
"TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
404
"isolated from them. Option automatically turns off --lock-tables.",
405
(char**) &opt_single_transaction, (char**) &opt_single_transaction, 0,
406
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
407
{"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
408
(char**) &opt_dump_date, (char**) &opt_dump_date, 0,
409
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
410
{"skip-opt", OPT_SKIP_OPTIMIZATION,
411
"Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
412
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
414
"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.",
415
(char**) &path, (char**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
416
{"tables", OPT_TABLES, "Overrides option --databases (-B).",
417
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
418
{"tz-utc", OPT_TZ_UTC,
419
"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.",
420
(char**) &opt_tz_utc, (char**) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
421
#ifndef DONT_ALLOW_USER_CHANGE
422
{"user", 'u', "User for login if not current user.",
423
(char**) ¤t_user, (char**) ¤t_user, 0, GET_STR, REQUIRED_ARG,
426
{"verbose", 'v', "Print info about the various stages.",
427
(char**) &verbose, (char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
428
{"version",'V', "Output version information and exit.", 0, 0, 0,
429
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
430
{"where", 'w', "Dump only selected records; QUOTES mandatory!",
431
(char**) &where, (char**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
432
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
433
NO_ARG, 0, 0, 0, 0, 0, 0},
434
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
437
static const char *load_default_groups[]= { "drizzledump","client",0 };
439
static void maybe_exit(int error);
124
440
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);
441
static void maybe_die(int error, const char* reason, ...);
442
static void write_header(FILE *sql_file, char *db_name);
443
static void print_value(FILE *file, DRIZZLE_RES *result, DRIZZLE_ROW row,
444
const char *prefix,const char *name,
446
static int dump_selected_tables(char *db, char **table_names, int tables);
447
static int dump_all_tables_in_db(char *db);
448
static int init_dumping_tables(char *);
449
static int init_dumping(char *, int init_func(char*));
450
static int dump_databases(char **);
128
451
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;
452
static char *quote_name(const char *name, char *buff, bool force);
453
char check_if_ignore_table(const char *table_name, char *table_type);
454
static char *primary_key_fields(const char *table_name);
457
Print the supplied message if in verbose mode
462
... variable number of parameters
464
static void verbose_msg(const char *fmt, ...)
473
vfprintf(stderr, fmt, args);
221
480
exit with message if ferror(file)
228
487
static void check_io(FILE *file)
230
489
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;
490
die(EX_EOF, "Got errno %d on write", errno);
493
static void print_version(void)
495
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
496
drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
497
} /* print_version */
500
static void short_usage_sub(void)
502
printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
503
printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
505
printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
509
static void usage(void)
512
puts("By Igor Romanenko, Monty, Jani & Sinisa");
513
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");
514
puts("Dumping definition and data DRIZZLE database or table");
516
print_defaults("my",load_default_groups);
517
my_print_help(my_long_options);
518
my_print_variables(my_long_options);
522
static void short_usage(void)
525
printf("For more options, use %s --help\n", my_progname);
528
static void write_header(FILE *sql_file, char *db_name)
532
fputs("<?xml version=\"1.0\"?>\n", sql_file);
534
Schema reference. Allows use of xsi:nil for NULL values and
535
xsi:type to define an element's data type.
537
fputs("<drizzledump ", sql_file);
538
fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
540
fputs(">\n", sql_file);
543
else if (!opt_compact)
548
"-- DRIZZLE dump %s Distrib %s, for %s (%s)\n--\n",
549
DUMP_VERSION, drizzle_get_client_info(),
550
SYSTEM_TYPE, MACHINE_TYPE);
551
fprintf(sql_file, "-- Host: %s Database: %s\n",
552
current_host ? current_host : "localhost", db_name ? db_name :
554
fputs("-- ------------------------------------------------------\n",
556
fprintf(sql_file, "-- Server version\t%s\n",
557
drizzle_get_server_info(&drizzle_connection));
561
"\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
562
"\n/*!40101 SET NAMES %s */;\n",default_charset);
566
fprintf(sql_file, "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n");
567
fprintf(sql_file, "/*!40103 SET TIME_ZONE='+00:00' */;\n");
572
fprintf(md_result_file,"\
573
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n\
574
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n\
250
579
} /* write_header */
253
582
static void write_footer(FILE *sql_file)
586
fputs("</drizzledump>\n", sql_file);
589
else if (!opt_compact)
592
fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n");
596
fprintf(md_result_file,"\
597
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
598
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
602
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
604
"/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
605
fputs("\n", sql_file);
257
606
if (opt_comments)
259
608
if (opt_dump_date)
261
boost::posix_time::ptime time(boost::posix_time::second_clock::local_time());
611
get_date(time_str, GETDATE_DATE_TIME, 0);
262
612
fprintf(sql_file, "-- Dump completed on %s\n",
263
boost::posix_time::to_simple_string(time).c_str());
266
616
fprintf(sql_file, "-- Dump completed\n");
312
901
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
315
fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
904
fprintf(stderr, "%s: %s\n", my_progname, buffer);
318
907
ignore_errors= 0; /* force the exit */
319
908
maybe_exit(error_num);
913
Prints out an error message and maybe kills the process.
917
error_num - process return value
918
fmt_reason - a format string for use by vsnprintf.
919
... - variable arguments for above fmt_reason string
922
This call prints out the formatted error message to stderr and then
923
terminates the process, unless the --force command line option is used.
925
This call should be used for non-fatal errors (such as database
926
errors) that the code may still be able to continue to the next unit
930
static void maybe_die(int error_num, const char* fmt_reason, ...)
934
va_start(args,fmt_reason);
935
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
938
fprintf(stderr, "%s: %s\n", my_progname, buffer);
941
maybe_exit(error_num);
947
Sends a query to server, optionally reads result, prints error message if
951
drizzle_query_with_error_report()
952
drizzle_con connection to use
953
res if non zero, result will be put there with
954
drizzle_store_result()
955
query query to send to server
958
0 query sending and (if res!=0) result reading went ok
962
static int drizzle_query_with_error_report(DRIZZLE *drizzle_con, DRIZZLE_RES **res,
965
if (drizzle_query(drizzle_con, query) ||
966
(res && !((*res)= drizzle_store_result(drizzle_con))))
968
maybe_die(EX_DRIZZLEERR, "Couldn't execute '%s': %s (%d)",
969
query, drizzle_error(drizzle_con), drizzle_errno(drizzle_con));
977
Switch charset for results to some specified charset. If the server does not
978
support character_set_results variable, nothing can be done here. As for
979
whether something should be done here, future new callers of this function
980
should be aware that the server lacking the facility of switching charsets is
983
@note If the server lacks support, then nothing is changed and no error
984
condition is returned.
986
@returns whether there was an error or not
988
static int switch_character_set_results(DRIZZLE *drizzle, const char *cs_name)
990
char query_buffer[QUERY_LENGTH];
993
/* Server lacks facility. This is not an error, by arbitrary decision . */
994
if (!server_supports_switching_charsets)
997
query_length= snprintf(query_buffer,
998
sizeof (query_buffer),
999
"SET SESSION character_set_results = '%s'",
1000
(const char *) cs_name);
1002
return drizzle_real_query(drizzle, query_buffer, query_length);
1006
Open a new .sql file to dump the table or view into
1009
open_sql_file_for_table
1010
name name of the table or view
1013
0 Failed to open file
1014
> 0 Handle of the open file
1016
static FILE* open_sql_file_for_table(const char* table)
1019
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
1020
convert_dirname(tmp_path,path,NullS);
1021
res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
1022
O_WRONLY, MYF(MY_WME));
322
1027
static void free_resources(void)
324
1029
if (md_result_file && md_result_file != stdout)
325
fclose(md_result_file);
326
opt_password.erase();
1030
my_fclose(md_result_file, MYF(0));
1031
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
1032
if (hash_inited(&ignore_table))
1033
hash_free(&ignore_table);
1035
free_defaults(defaults_argv);
330
void maybe_exit(int error)
1040
static void maybe_exit(int error)
332
1042
if (!first_error)
333
1043
first_error= error;
334
1044
if (ignore_errors)
336
delete db_connection;
337
delete destination_connection;
1047
drizzle_close(drizzle);
338
1048
free_resources();
1054
db_connect -- connects to the host and selects DB.
1057
static int connect_to_db(char *host, char *user,char *passwd)
1059
char buff[20+FN_REFLEN];
1062
verbose_msg("-- Connecting to %s...\n", host ? host : "localhost");
1063
drizzle_create(&drizzle_connection);
1065
drizzle_options(&drizzle_connection,DRIZZLE_OPT_COMPRESS,NullS);
1067
drizzle_options(&drizzle_connection,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
1068
drizzle_options(&drizzle_connection, DRIZZLE_SET_CHARSET_NAME, default_charset);
1069
if (!(drizzle= drizzle_connect(&drizzle_connection,host,user,passwd,
1070
NULL,opt_drizzle_port, NULL,
1073
DB_error(&drizzle_connection, "when trying to connect");
1076
if (drizzle_get_server_version(&drizzle_connection) < 40100)
1078
/* Don't dump SET NAMES with a pre-4.1 server (bug#7997). */
1081
/* Don't switch charsets for 4.1 and earlier. (bug#34192). */
1082
server_supports_switching_charsets= false;
1085
set time_zone to UTC to allow dumping date types between servers with
1086
different time zone settings
1090
snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */");
1091
if (drizzle_query_with_error_report(drizzle, 0, buff))
1095
} /* connect_to_db */
1099
** dbDisconnect -- disconnects from the host.
1101
static void dbDisconnect(char *host)
1103
verbose_msg("-- Disconnecting from %s...\n", host ? host : "localhost");
1104
drizzle_close(drizzle);
1105
} /* dbDisconnect */
1108
static void unescape(FILE *file,char *pos,uint length)
1112
if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
1113
die(EX_DRIZZLEERR, "Couldn't allocate memory");
1115
drizzle_real_escape_string(&drizzle_connection, tmp, pos, length);
1120
my_free(tmp, MYF(MY_WME));
1125
static bool test_if_special_chars(const char *str)
1127
for ( ; *str ; str++)
1128
if (!my_isvar(charset_info,*str) && *str != '$')
1131
} /* test_if_special_chars */
1136
quote_name(name, buff, force)
1138
Quotes char string, taking into account compatible mode
1142
name Unquoted string containing that which will be quoted
1143
buff The buffer that contains the quoted value, also returned
1144
force Flag to make it ignore 'test_if_special_chars'
1151
static char *quote_name(const char *name, char *buff, bool force)
1154
char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';
1156
if (!force && !opt_quoted && !test_if_special_chars(name))
1157
return (char*) name;
1172
Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
1176
name name of the table
1177
buff quoted name of the table
1180
Quote \, _, ' and % characters
1182
Note: Because DRIZZLE uses the C escape syntax in strings
1183
(for example, '\n' to represent newline), you must double
1184
any '\' that you use in your LIKE strings. For example, to
1185
search for '\n', specify it as '\\n'. To search for '\', specify
1186
it as '\\\\' (the backslashes are stripped once by the parser
1187
and another time when the pattern match is done, leaving a
1188
single backslash to be matched).
1190
Example: "t\1" => "t\\\\1"
1193
static char *quote_for_like(const char *name, char *buff)
1205
else if (*name == '\'' || *name == '_' || *name == '%')
1216
Quote and print a string.
1220
xml_file - output file
1221
str - string to print
1225
Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1228
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
1232
for (end= str + len; str != end; str++)
1236
fputs("<", xml_file);
1239
fputs(">", xml_file);
1242
fputs("&", xml_file);
1245
fputs(""", xml_file);
1248
fputc(*str, xml_file);
1257
Print xml tag. Optionally add attribute(s).
1260
print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
1261
..., attribute_name_n, attribute_value_n, NullS)
1262
xml_file - output file
1263
sbeg - line beginning
1264
line_end - line ending
1265
tag_name - XML tag name.
1266
first_attribute_name - tag and first attribute
1267
first_attribute_value - (Implied) value of first attribute
1268
attribute_name_n - attribute n
1269
attribute_value_n - value of attribute n
1272
Print XML tag with any number of attribute="value" pairs to the xml_file.
1275
sbeg<tag_name first_attribute_name="first_attribute_value" ...
1276
attribute_name_n="attribute_value_n">send
1278
Additional arguments must be present in attribute/value pairs.
1279
The last argument should be the null character pointer.
1280
All attribute_value arguments MUST be NULL terminated strings.
1281
All attribute_value arguments will be quoted before output.
1284
static void print_xml_tag(FILE * xml_file, const char* sbeg,
1285
const char* line_end,
1286
const char* tag_name,
1287
const char* first_attribute_name, ...)
1290
const char *attribute_name, *attribute_value;
1292
fputs(sbeg, xml_file);
1293
fputc('<', xml_file);
1294
fputs(tag_name, xml_file);
1296
va_start(arg_list, first_attribute_name);
1297
attribute_name= first_attribute_name;
1298
while (attribute_name != NullS)
1300
attribute_value= va_arg(arg_list, char *);
1301
assert(attribute_value != NullS);
1303
fputc(' ', xml_file);
1304
fputs(attribute_name, xml_file);
1305
fputc('\"', xml_file);
1307
print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
1308
fputc('\"', xml_file);
1310
attribute_name= va_arg(arg_list, char *);
1314
fputc('>', xml_file);
1315
fputs(line_end, xml_file);
1321
Print xml tag with for a field that is null
1324
print_xml_null_tag()
1325
xml_file - output file
1326
sbeg - line beginning
1327
stag_atr - tag and attribute
1328
sval - value of attribute
1329
line_end - line ending
1332
Print tag with one attribute to the xml_file. Format is:
1333
<stag_atr="sval" xsi:nil="true"/>
1335
sval MUST be a NULL terminated string.
1336
sval string will be qouted before output.
1339
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
1340
const char* stag_atr, const char* sval,
1341
const char* line_end)
1343
fputs(sbeg, xml_file);
1344
fputs("<", xml_file);
1345
fputs(stag_atr, xml_file);
1346
fputs("\"", xml_file);
1347
print_quoted_xml(xml_file, sval, strlen(sval));
1348
fputs("\" xsi:nil=\"true\" />", xml_file);
1349
fputs(line_end, xml_file);
1355
Print xml tag with many attributes.
1359
xml_file - output file
1360
row_name - xml tag name
1361
tableRes - query result
1365
Print tag with many attribute to the xml_file. Format is:
1366
\t\t<row_name Atr1="Val1" Atr2="Val2"... />
1368
All atributes and values will be quoted before output.
1371
static void print_xml_row(FILE *xml_file, const char *row_name,
1372
DRIZZLE_RES *tableRes, DRIZZLE_ROW *row)
1375
DRIZZLE_FIELD *field;
1376
uint32_t *lengths= drizzle_fetch_lengths(tableRes);
1378
fprintf(xml_file, "\t\t<%s", row_name);
1380
drizzle_field_seek(tableRes, 0);
1381
for (i= 0; (field= drizzle_fetch_field(tableRes)); i++)
1385
fputc(' ', xml_file);
1386
print_quoted_xml(xml_file, field->name, field->name_length);
1387
fputs("=\"", xml_file);
1388
print_quoted_xml(xml_file, (*row)[i], lengths[i]);
1389
fputc('"', xml_file);
1393
fputs(" />\n", xml_file);
1399
Print hex value for blob data.
1403
output_file - output file
1404
str - string to print
1408
Print hex value for blob data.
1411
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
1413
/* sakaik got the idea to to provide blob's in hex notation. */
1414
const char *ptr= str, *end= ptr + len;
1415
for (; ptr < end ; ptr++)
1416
fprintf(output_file, "%02X", *((uchar *)ptr));
1417
check_io(output_file);
1421
get_table_structure -- retrievs database structure, prints out corresponding
1422
CREATE statement and fills out insert_pat if the table is the type we will
1428
table_type - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
1429
ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1432
number of fields in table, 0 if error
1435
static uint get_table_structure(char *table, char *db, char *table_type,
1438
bool init=0, delayed, write_data, complete_insert;
1439
uint64_t num_fields;
1440
char *result_table, *opt_quoted_table;
1441
const char *insert_option;
1442
char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
1443
char table_buff2[NAME_LEN*2+3], query_buff[QUERY_LENGTH];
1444
FILE *sql_file= md_result_file;
1446
DRIZZLE_RES *result;
1449
*ignore_flag= check_if_ignore_table(table, table_type);
1451
delayed= opt_delayed;
1452
if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
1455
verbose_msg("-- Warning: Unable to use delayed inserts for table '%s' "
1456
"because it's of type %s\n", table, table_type);
1460
if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1462
complete_insert= opt_complete_insert;
1466
insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
1467
delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
1469
verbose_msg("-- Retrieving table structure for table %s...\n", table);
1471
len= snprintf(query_buff, sizeof(query_buff),
1472
"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
1473
(opt_quoted || opt_keywords));
1475
result_table= quote_name(table, table_buff, 1);
1476
opt_quoted_table= quote_name(table, table_buff2, 0);
1478
if (opt_order_by_primary)
1480
my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
1481
order_by= primary_key_fields(result_table);
1484
if (!opt_xml && !drizzle_query_with_error_report(drizzle, 0, query_buff))
1486
/* using SHOW CREATE statement */
1487
if (!opt_no_create_info)
1489
/* Make an sql-file, if path was given iow. option -T was given */
1490
char buff[20+FN_REFLEN];
1491
const DRIZZLE_FIELD *field;
1493
snprintf(buff, sizeof(buff), "show create table %s", result_table);
1495
if (switch_character_set_results(drizzle, "binary") ||
1496
drizzle_query_with_error_report(drizzle, &result, buff) ||
1497
switch_character_set_results(drizzle, default_charset))
1502
if (!(sql_file= open_sql_file_for_table(table)))
1505
write_header(sql_file, db);
1507
if (!opt_xml && opt_comments)
1509
if (strcmp (table_type, "VIEW") == 0) /* view */
1510
fprintf(sql_file, "\n--\n-- Temporary table structure for view %s\n--\n\n",
1513
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1520
Even if the "table" is a view, we do a DROP TABLE here. The
1521
view-specific code below fills in the DROP VIEW.
1523
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
1528
field= drizzle_fetch_field_direct(result, 0);
1529
if (strcmp(field->name, "View") == 0)
1531
char *scv_buff= NULL;
1533
verbose_msg("-- It's a view, create dummy table for view\n");
1535
/* save "show create" statement for later */
1536
if ((row= drizzle_fetch_row(result)) && (scv_buff=row[1]))
1537
scv_buff= my_strdup(scv_buff, MYF(0));
1539
drizzle_free_result(result);
1542
Create a table with the same name as the view and with columns of
1543
the same name in order to satisfy views that depend on this view.
1544
The table will be removed when the actual view is created.
1546
The properties of each column, aside from the data type, are not
1547
preserved in this temporary table, because they are not necessary.
1549
This will not be necessary once we can determine dependencies
1550
between views and can simply dump them in the appropriate order.
1552
snprintf(query_buff, sizeof(query_buff),
1553
"SHOW FIELDS FROM %s", result_table);
1554
if (switch_character_set_results(drizzle, "binary") ||
1555
drizzle_query_with_error_report(drizzle, &result, query_buff) ||
1556
switch_character_set_results(drizzle, default_charset))
1559
View references invalid or privileged table/col/fun (err 1356),
1560
so we cannot create a stand-in table. Be defensive and dump
1561
a comment with the view's 'show create' statement. (Bug #17371)
1564
if (drizzle_errno(drizzle) == ER_VIEW_INVALID)
1565
fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : "");
1567
my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
1572
my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
1574
if (drizzle_num_rows(result))
1579
We have already dropped any table of the same name above, so
1580
here we just drop the view.
1583
fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
1589
"/*!50001 CREATE TABLE %s (\n",
1593
Get first row, following loop will prepend comma - keeps from
1594
having to know if the row being printed is last to determine if
1595
there should be a _trailing_ comma.
1598
row= drizzle_fetch_row(result);
1600
fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0),
1603
while((row= drizzle_fetch_row(result)))
1605
/* col name, col type */
1606
fprintf(sql_file, ",\n %s %s",
1607
quote_name(row[0], name_buff, 0), row[1]);
1609
fprintf(sql_file, "\n) */;\n");
1613
drizzle_free_result(result);
1616
my_fclose(sql_file, MYF(MY_WME));
1622
row= drizzle_fetch_row(result);
1624
fprintf(sql_file, "%s;\n", row[1]);
1627
drizzle_free_result(result);
1629
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1631
if (drizzle_query_with_error_report(drizzle, &result, query_buff))
1634
my_fclose(sql_file, MYF(MY_WME));
1639
If write_data is true, then we build up insert statements for
1640
the table's data. Note: in subsequent lines of code, this test
1641
will have to be performed each time we are appending to
1646
if (opt_replace_into)
1647
insert_pat.append("REPLACE ");
1649
insert_pat.append("INSERT ");
1650
insert_pat.append(insert_option);
1651
insert_pat.append("INTO ");
1652
insert_pat.append(opt_quoted_table);
1653
if (complete_insert)
1655
insert_pat.append(" (");
1659
insert_pat.append(" VALUES ");
1660
if (!extended_insert)
1661
insert_pat.append("(");
1665
while ((row= drizzle_fetch_row(result)))
1667
if (complete_insert)
1671
insert_pat.append(", ");
1674
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1677
num_fields= drizzle_num_rows(result);
1678
drizzle_free_result(result);
1682
verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
1683
my_progname, drizzle_error(drizzle));
1685
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1687
if (drizzle_query_with_error_report(drizzle, &result, query_buff))
1690
/* Make an sql-file, if path was given iow. option -T was given */
1691
if (!opt_no_create_info)
1695
if (!(sql_file= open_sql_file_for_table(table)))
1697
write_header(sql_file, db);
1699
if (!opt_xml && opt_comments)
1700
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1703
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1705
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
1707
print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
1714
if (opt_replace_into)
1715
insert_pat.append("REPLACE ");
1717
insert_pat.append("INSERT ");
1718
insert_pat.append(insert_option);
1719
insert_pat.append("INTO ");
1720
insert_pat.append(result_table);
1721
if (complete_insert)
1722
insert_pat.append(" (");
1725
insert_pat.append(" VALUES ");
1726
if (!extended_insert)
1727
insert_pat.append("(");
1731
while ((row= drizzle_fetch_row(result)))
1733
uint32_t *lengths= drizzle_fetch_lengths(result);
1736
if (!opt_xml && !opt_no_create_info)
1738
fputs(",\n",sql_file);
1741
if (complete_insert)
1742
insert_pat.append(", ");
1745
if (complete_insert)
1746
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1747
if (!opt_no_create_info)
1751
print_xml_row(sql_file, "field", result, &row);
1756
fprintf(sql_file, " %s.%s %s", result_table,
1757
quote_name(row[SHOW_FIELDNAME],name_buff, 0),
1760
fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
1763
if (row[SHOW_DEFAULT])
1765
fputs(" DEFAULT ", sql_file);
1766
unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1768
if (!row[SHOW_NULL][0])
1769
fputs(" NOT NULL", sql_file);
1770
if (row[SHOW_EXTRA][0])
1771
fprintf(sql_file, " %s",row[SHOW_EXTRA]);
1775
num_fields= drizzle_num_rows(result);
1776
drizzle_free_result(result);
1777
if (!opt_no_create_info)
1779
/* Make an sql-file, if path was given iow. option -T was given */
1780
char buff[20+FN_REFLEN];
1781
uint keynr,primary_key;
1782
snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1783
if (drizzle_query_with_error_report(drizzle, &result, buff))
1785
if (drizzle_errno(drizzle) == ER_WRONG_OBJECT)
1788
fputs("\t\t<options Comment=\"view\" />\n", sql_file);
1791
fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
1792
my_progname, result_table, drizzle_error(drizzle));
1794
my_fclose(sql_file, MYF(MY_WME));
1798
/* Find first which key is primary key */
1800
primary_key=INT_MAX;
1801
while ((row= drizzle_fetch_row(result)))
1803
if (atoi(row[3]) == 1)
1806
#ifdef FORCE_PRIMARY_KEY
1807
if (atoi(row[1]) == 0 && primary_key == INT_MAX)
1810
if (!strcmp(row[2],"PRIMARY"))
1817
drizzle_data_seek(result,0);
1819
while ((row= drizzle_fetch_row(result)))
1823
print_xml_row(sql_file, "key", result, &row);
1827
if (atoi(row[3]) == 1)
1830
putc(')', sql_file);
1831
if (atoi(row[1])) /* Test if duplicate key */
1832
/* Duplicate allowed */
1833
fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0));
1834
else if (keynr == primary_key)
1835
fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
1837
fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
1841
putc(',', sql_file);
1842
fputs(quote_name(row[4], name_buff, 0), sql_file);
1844
fprintf(sql_file, " (%s)",row[7]); /* Sub key */
1847
drizzle_free_result(result);
1851
putc(')', sql_file);
1852
fputs("\n)",sql_file);
1856
/* Get DRIZZLE specific create options */
1859
char show_name_buff[NAME_LEN*2+2+24];
1861
/* Check memory for quote_for_like() */
1862
snprintf(buff, sizeof(buff), "show table status like %s",
1863
quote_for_like(table, show_name_buff));
1865
if (drizzle_query_with_error_report(drizzle, &result, buff))
1867
if (drizzle_errno(drizzle) != ER_PARSE_ERROR)
1868
{ /* If old DRIZZLE version */
1869
verbose_msg("-- Warning: Couldn't get status information for " \
1870
"table %s (%s)\n", result_table,drizzle_error(drizzle));
1873
else if (!(row= drizzle_fetch_row(result)))
1876
"Error: Couldn't read status information for table %s (%s)\n",
1877
result_table,drizzle_error(drizzle));
1882
print_xml_row(sql_file, "options", result, &row);
1885
fputs("/*!",sql_file);
1886
print_value(sql_file,result,row,"engine=","Engine",0);
1887
print_value(sql_file,result,row,"","Create_options",0);
1888
print_value(sql_file,result,row,"comment=","Comment",1);
1889
fputs(" */",sql_file);
1893
drizzle_free_result(result); /* Is always safe to free */
1897
fputs(";\n", sql_file);
1899
fputs("\t</table_structure>\n", sql_file);
1903
if (complete_insert)
1905
insert_pat.append(") VALUES ");
1906
if (!extended_insert)
1907
insert_pat.append("(");
1909
if (sql_file != md_result_file)
1911
fputs("\n", sql_file);
1912
write_footer(sql_file);
1913
my_fclose(sql_file, MYF(MY_WME));
1915
return((uint) num_fields);
1916
} /* get_table_structure */
1918
static void add_load_option(string &str, const char *option,
1919
const char *option_value)
1923
/* Null value means we don't add this option. */
1929
if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
1931
/* It's a hex constant, don't escape */
1932
str.append(option_value);
1936
/* char constant; escape */
1937
field_escape(str, option_value);
1943
Allow the user to specify field terminator strings like:
1944
"'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
1945
This is done by doubling ' and add a end -\ if needed to avoid
1946
syntax errors from the SQL parser.
1949
static void field_escape(string &in, const char *from)
1951
uint end_backslashes= 0;
1960
end_backslashes^=1; /* find odd number of backslashes */
1963
if (*from == '\'' && !end_backslashes)
1965
/* We want a duplicate of "'" for DRIZZLE */
1972
/* Add missing backslashes if user has specified odd number of backs.*/
1973
if (end_backslashes)
1986
dump_table saves database contents as a series of INSERT statements.
1997
static void dump_table(char *table, char *db)
2000
char buf[200], table_buff[NAME_LEN+3];
2001
string query_string;
2002
char table_type[NAME_LEN];
2003
char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
2005
uint32_t rownr, row_break, total_length, init_length;
2008
DRIZZLE_FIELD *field;
2013
Make sure you get the create table info before the following check for
2014
--no-data flag below. Otherwise, the create table info won't be printed.
2016
num_fields= get_table_structure(table, db, table_type, &ignore_flag);
2019
The "table" could be a view. If so, we don't do anything here.
2021
if (strcmp(table_type, "VIEW") == 0)
2024
/* Check --no-data flag */
2027
verbose_msg("-- Skipping dump data for table '%s', --no-data was used\n",
2033
If the table type is a merge table or any type that has to be
2034
_completely_ ignored and no data dumped
2036
if (ignore_flag & IGNORE_DATA)
2038
verbose_msg("-- Warning: Skipping data for table '%s' because " \
2039
"it's of type %s\n", table, table_type);
2042
/* Check that there are any fields in the table */
2043
if (num_fields == 0)
2045
verbose_msg("-- Skipping dump data for table '%s', it has no fields\n",
2051
Check --skip-events flag: it is not enough to skip creation of events
2052
discarding SHOW CREATE EVENT statements generation. The myslq.event
2053
table data should be skipped too.
2055
if (!opt_events && !my_strcasecmp(&my_charset_latin1, db, "mysql") &&
2056
!my_strcasecmp(&my_charset_latin1, table, "event"))
2058
verbose_msg("-- Skipping data table mysql.event, --skip-events was used\n");
2062
result_table= quote_name(table,table_buff, 1);
2063
opt_quoted_table= quote_name(table, table_buff2, 0);
2065
verbose_msg("-- Sending SELECT query...\n");
2067
query_string.clear();
2068
query_string.reserve(1024);
2072
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
2075
Convert the path to native os format
2076
and resolve to the full filepath.
2078
convert_dirname(tmp_path,path,NullS);
2079
my_load_path(tmp_path, tmp_path, NULL);
2080
fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
2082
/* Must delete the file that 'INTO OUTFILE' will write to */
2083
my_delete(filename, MYF(0));
2085
/* convert to a unix path name to stick into the query */
2086
to_unix_path(filename);
2088
/* now build the query string */
2090
query_string.append( "SELECT * INTO OUTFILE '");
2091
query_string.append( filename);
2092
query_string.append( "'");
2094
if (fields_terminated || enclosed || opt_enclosed || escaped)
2095
query_string.append( " FIELDS");
2097
add_load_option(query_string, " TERMINATED BY ", fields_terminated);
2098
add_load_option(query_string, " ENCLOSED BY ", enclosed);
2099
add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
2100
add_load_option(query_string, " ESCAPED BY ", escaped);
2101
add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
2103
query_string.append( " FROM ");
2104
query_string.append( result_table);
2108
query_string.append( " WHERE ");
2109
query_string.append( where);
2114
query_string.append( " ORDER BY ");
2115
query_string.append( order_by);
2118
if (drizzle_real_query(drizzle, query_string.c_str(), query_string.length()))
2120
DB_error(drizzle, "when executing 'SELECT INTO OUTFILE'");
2126
if (!opt_xml && opt_comments)
2128
fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
2130
check_io(md_result_file);
2133
query_string.append( "SELECT * FROM ");
2134
query_string.append( result_table);
2138
if (!opt_xml && opt_comments)
2140
fprintf(md_result_file, "-- WHERE: %s\n", where);
2141
check_io(md_result_file);
2144
query_string.append( " WHERE ");
2145
query_string.append( where);
2149
if (!opt_xml && opt_comments)
2151
fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
2152
check_io(md_result_file);
2154
query_string.append( " ORDER BY ");
2155
query_string.append( order_by);
2158
if (!opt_xml && !opt_compact)
2160
fputs("\n", md_result_file);
2161
check_io(md_result_file);
2163
if (drizzle_query_with_error_report(drizzle, 0, query_string.c_str()))
2165
DB_error(drizzle, "when retrieving data from server");
2169
res=drizzle_use_result(drizzle);
2171
res=drizzle_store_result(drizzle);
2174
DB_error(drizzle, "when retrieving data from server");
2178
verbose_msg("-- Retrieving rows...\n");
2179
if (drizzle_num_fields(res) != num_fields)
2181
fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n",
2182
my_progname, result_table);
2183
error= EX_CONSCHECK;
2189
fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
2190
check_io(md_result_file);
2192
/* Moved disable keys to after lock per bug 15977 */
2193
if (opt_disable_keys)
2195
fprintf(md_result_file, "/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
2197
check_io(md_result_file);
2200
total_length= opt_net_buffer_length; /* Force row break */
2203
init_length=(uint) insert_pat.length()+4;
2205
print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
2209
fprintf(md_result_file, "set autocommit=0;\n");
2210
check_io(md_result_file);
2213
while ((row= drizzle_fetch_row(res)))
2216
uint32_t *lengths= drizzle_fetch_lengths(res);
2218
if (!extended_insert && !opt_xml)
2220
fputs(insert_pat.c_str(),md_result_file);
2221
check_io(md_result_file);
2223
drizzle_field_seek(res,0);
2227
fputs("\t<row>\n", md_result_file);
2228
check_io(md_result_file);
2231
for (i= 0; i < drizzle_num_fields(res); i++)
2234
uint32_t length= lengths[i];
2236
if (!(field= drizzle_fetch_field(res)))
2238
"Not enough fields from table %s! Aborting.\n",
2242
63 is my_charset_bin. If charsetnr is not 63,
2243
we have not a BLOB but a TEXT column.
2244
we'll dump in hex only BLOB columns.
2246
is_blob= (opt_hex_blob && field->charsetnr == 63 &&
2247
(field->type == DRIZZLE_TYPE_VARCHAR ||
2248
field->type == DRIZZLE_TYPE_BLOB)) ? 1 : 0;
2249
if (extended_insert && !opt_xml)
2254
extended_row.append(",");
2260
if (!IS_NUM_FIELD(field))
2263
"length * 2 + 2" is OK for both HEX and non-HEX modes:
2264
- In HEX mode we need exactly 2 bytes per character
2265
plus 2 bytes for '0x' prefix.
2266
- In non-HEX mode we need up to 2 bytes per character,
2267
plus 2 bytes for leading and trailing '\'' characters.
2268
Also we need to reserve 1 byte for terminating '\0'.
2270
char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
2271
memset(tmp_str, '\0', length * 2 + 2 + 1);
2272
if (opt_hex_blob && is_blob)
2274
extended_row.append("0x");
2275
drizzle_hex_string(tmp_str, row[i], length);
2276
extended_row.append(tmp_str);
2280
extended_row.append("'");
2281
drizzle_real_escape_string(&drizzle_connection,
2284
extended_row.append(tmp_str);
2285
extended_row.append("'");
2291
/* change any strings ("inf", "-inf", "nan") into NULL */
2293
if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
2294
my_isalpha(charset_info, ptr[1])))
2295
extended_row.append( "NULL");
2298
extended_row.append( ptr);
2303
extended_row.append("''");
2306
extended_row.append("NULL");
2312
fputc(',', md_result_file);
2313
check_io(md_result_file);
2317
if (!IS_NUM_FIELD(field))
2321
if (opt_hex_blob && is_blob && length)
2323
/* Define xsi:type="xs:hexBinary" for hex encoded data */
2324
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2325
field->name, "xsi:type=", "xs:hexBinary", NullS);
2326
print_blob_as_hex(md_result_file, row[i], length);
2330
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2331
field->name, NullS);
2332
print_quoted_xml(md_result_file, row[i], length);
2334
fputs("</field>\n", md_result_file);
2336
else if (opt_hex_blob && is_blob && length)
2338
fputs("0x", md_result_file);
2339
print_blob_as_hex(md_result_file, row[i], length);
2342
unescape(md_result_file, row[i], length);
2346
/* change any strings ("inf", "-inf", "nan") into NULL */
2350
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2351
field->name, NullS);
2352
fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
2354
fputs("</field>\n", md_result_file);
2356
else if (my_isalpha(charset_info, *ptr) ||
2357
(*ptr == '-' && my_isalpha(charset_info, ptr[1])))
2358
fputs("NULL", md_result_file);
2360
fputs(ptr, md_result_file);
2365
/* The field value is NULL */
2367
fputs("NULL", md_result_file);
2369
print_xml_null_tag(md_result_file, "\t\t", "field name=",
2372
check_io(md_result_file);
2378
fputs("\t</row>\n", md_result_file);
2379
check_io(md_result_file);
2382
if (extended_insert)
2384
uint32_t row_length;
2385
extended_row.append(")");
2386
row_length= 2 + extended_row.length();
2387
if (total_length + row_length < opt_net_buffer_length)
2389
total_length+= row_length;
2390
fputc(',',md_result_file); /* Always row break */
2391
fputs(extended_row.c_str(),md_result_file);
2396
fputs(";\n", md_result_file);
2397
row_break=1; /* This is first row */
2399
fputs(insert_pat.c_str(),md_result_file);
2400
fputs(extended_row.c_str(),md_result_file);
2401
total_length= row_length+init_length;
2403
check_io(md_result_file);
2407
fputs(");\n", md_result_file);
2408
check_io(md_result_file);
2412
/* XML - close table tag and supress regular output */
2414
fputs("\t</table_data>\n", md_result_file);
2415
else if (extended_insert && row_break)
2416
fputs(";\n", md_result_file); /* If not empty table */
2417
fflush(md_result_file);
2418
check_io(md_result_file);
2419
if (drizzle_errno(drizzle))
2421
snprintf(buf, sizeof(buf),
2422
"%s: Error %d: %s when dumping table %s at row: %d\n",
2424
drizzle_errno(drizzle),
2425
drizzle_error(drizzle),
2429
error= EX_CONSCHECK;
2433
/* Moved enable keys to before unlock per bug 15977 */
2434
if (opt_disable_keys)
2436
fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
2438
check_io(md_result_file);
2442
fputs("UNLOCK TABLES;\n", md_result_file);
2443
check_io(md_result_file);
2447
fprintf(md_result_file, "commit;\n");
2448
check_io(md_result_file);
2450
drizzle_free_result(res);
2460
static char *getTableName(int reset)
2462
static DRIZZLE_RES *res= NULL;
2467
if (!(res= drizzle_list_tables(drizzle,NullS)))
2470
if ((row= drizzle_fetch_row(res)))
2471
return((char*) row[0]);
2474
drizzle_data_seek(res,0); /* We want to read again */
2477
drizzle_free_result(res);
2481
} /* getTableName */
342
2484
static int dump_all_databases()
345
drizzle_result_st *tableres;
2487
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)))
2490
if (drizzle_query_with_error_report(drizzle, &tableres, "SHOW DATABASES"))
2492
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);
2494
if (dump_all_tables_in_db(row[0]))
371
db_connection->freeResult(tableres);
374
2499
/* dump_all_databases */
377
static int dump_databases(const vector<string> &db_names)
2502
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)
2508
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);
2510
if (dump_all_tables_in_db(*db))
393
2514
} /* 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);
2518
Table Specific database initalization.
2522
qdatabase quoted name of the database
2529
int init_dumping_tables(char *qdatabase)
2537
DRIZZLE_RES *dbinfo;
2539
snprintf(qbuf, sizeof(qbuf),
2540
"SHOW CREATE DATABASE IF NOT EXISTS %s",
2543
if (drizzle_query(drizzle, qbuf) || !(dbinfo = drizzle_store_result(drizzle)))
2545
/* Old server version, dump generic CREATE DATABASE */
2546
if (opt_drop_database)
2547
fprintf(md_result_file,
2548
"\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
2550
fprintf(md_result_file,
2551
"\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
2556
if (opt_drop_database)
2557
fprintf(md_result_file,
2558
"\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
2560
row = drizzle_fetch_row(dbinfo);
2563
fprintf(md_result_file,"\n%s;\n",row[1]);
2565
drizzle_free_result(dbinfo);
2569
} /* init_dumping_tables */
2572
static int init_dumping(char *database, int init_func(char*))
2574
if (drizzle_get_server_version(drizzle) >= 50003 &&
2575
!my_strcasecmp(&my_charset_latin1, database, "information_schema"))
2578
if (drizzle_select_db(drizzle, database))
2580
DB_error(drizzle, "when selecting the database");
2581
return 1; /* If --force */
2583
if (!path && !opt_xml)
2585
if (opt_databases || opt_alldbs)
2588
length of table name * 2 (if name contains quotes), 2 quotes and 0
2590
char quoted_database_buf[NAME_LEN*2+3];
2591
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
2594
fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
2595
check_io(md_result_file);
2598
/* Call the view or table specific function */
2599
init_func(qdatabase);
2601
fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
2602
check_io(md_result_file);
2605
if (extended_insert)
2606
extended_row.clear();
2608
} /* init_dumping */
2611
/* Return 1 if we should copy the table */
2613
static bool include_table(const uchar *hash_key, size_t len)
2615
return !hash_search(&ignore_table, hash_key, len);
2619
static int dump_all_tables_in_db(char *database)
2623
char table_buff[NAME_LEN*2+3];
2624
char hash_key[2*NAME_LEN+2]; /* "db.tablename" */
2626
int using_mysql_db= my_strcasecmp(&my_charset_latin1, database, "mysql");
2629
afterdot= stpcpy(hash_key, database);
2632
if (init_dumping(database, init_dumping_tables))
2635
print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
2639
query= "LOCK TABLES ";
2640
for (numrows= 0 ; (table= getTableName(1)) ; )
2642
char *end= stpcpy(afterdot, table);
2643
if (include_table((uchar*) hash_key,end - hash_key))
2646
query.append( quote_name(table, table_buff, 1));
2647
query.append( " READ /*!32311 LOCAL */,");
2650
if (numrows && drizzle_real_query(drizzle, query.c_str(), query.length()-1))
2651
DB_error(drizzle, "when using LOCK TABLES");
2652
/* We shall continue here, if --force was given */
2657
if (drizzle_refresh(drizzle, REFRESH_LOG))
2658
DB_error(drizzle, "when doing refresh");
2659
/* We shall continue here, if --force was given */
2661
while ((table= getTableName(0)))
2663
char *end= stpcpy(afterdot, table);
2664
if (include_table((uchar*) hash_key, end - hash_key))
2666
dump_table(table,database);
2667
my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
2673
fputs("</database>\n", md_result_file);
2674
check_io(md_result_file);
2677
VOID(drizzle_query_with_error_report(drizzle, 0, "UNLOCK TABLES"));
2678
if (flush_privileges && using_mysql_db == 0)
2680
fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n");
2681
fprintf(md_result_file,"\n/*! FLUSH PRIVILEGES */;\n");
2684
} /* dump_all_tables_in_db */
2688
get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
2689
table name from the server for the table name given on the command line.
2690
we do this because the table name given on the command line may be a
2691
different case (e.g. T1 vs t1)
2694
pointer to the table name
2698
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
2701
DRIZZLE_RES *table_res;
2703
char query[50 + 2*NAME_LEN];
2704
char show_name_buff[FN_REFLEN];
2707
/* Check memory for quote_for_like() */
2708
assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
2709
snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
2710
quote_for_like(old_table_name, show_name_buff));
2712
if (drizzle_query_with_error_report(drizzle, 0, query))
2715
if ((table_res= drizzle_store_result(drizzle)))
2717
uint64_t num_rows= drizzle_num_rows(table_res);
2723
TODO: Return all matching rows
2725
row= drizzle_fetch_row(table_res);
2726
lengths= drizzle_fetch_lengths(table_res);
2727
name= strmake_root(root, row[0], lengths[0]);
2729
drizzle_free_result(table_res);
2735
static int dump_selected_tables(char *db, char **table_names, int tables)
2737
char table_buff[NAME_LEN*2+3];
2738
string lock_tables_query;
2740
char **dump_tables, **pos, **end;
2743
if (init_dumping(db, init_dumping_tables))
2746
init_alloc_root(&root, 8192, 0);
2747
if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
2748
die(EX_EOM, "alloc_root failure.");
2750
lock_tables_query= "LOCK TABLES ";
2751
for (; tables > 0 ; tables-- , table_names++)
2753
/* the table name passed on commandline may be wrong case */
2754
if ((*pos= get_actual_table_name(*table_names, &root)))
2756
/* Add found table name to lock_tables_query */
2759
lock_tables_query.append( quote_name(*pos, table_buff, 1));
2760
lock_tables_query.append( " READ /*!32311 LOCAL */,");
2768
free_root(&root, MYF(0));
2770
maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
2771
/* We shall countinue here, if --force was given */
2778
if (drizzle_real_query(drizzle, lock_tables_query.c_str(),
2779
lock_tables_query.length()-1))
2783
free_root(&root, MYF(0));
2785
DB_error(drizzle, "when doing LOCK TABLES");
2786
/* We shall countinue here, if --force was given */
2791
if (drizzle_refresh(drizzle, REFRESH_LOG))
2794
free_root(&root, MYF(0));
2795
DB_error(drizzle, "when doing refresh");
2797
/* We shall countinue here, if --force was given */
2800
print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NullS);
2802
/* Dump each selected table */
2803
for (pos= dump_tables; pos < end; pos++)
2804
dump_table(*pos, db);
2806
free_root(&root, MYF(0));
2807
my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
2811
fputs("</database>\n", md_result_file);
2812
check_io(md_result_file);
2815
VOID(drizzle_query_with_error_report(drizzle, 0, "UNLOCK TABLES"));
414
2817
} /* dump_selected_tables */
416
static int do_flush_tables_read_lock()
2820
static int do_show_master_status(DRIZZLE *drizzle_con)
2823
DRIZZLE_RES *master;
2824
const char *comment_prefix=
2825
(opt_master_data == DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
2826
if (drizzle_query_with_error_report(drizzle_con, &master, "SHOW MASTER STATUS"))
2832
row= drizzle_fetch_row(master);
2833
if (row && row[0] && row[1])
2835
/* SHOW MASTER STATUS reports file and position */
2837
fprintf(md_result_file,
2838
"\n--\n-- Position to start replication or point-in-time "
2839
"recovery from\n--\n\n");
2840
fprintf(md_result_file,
2841
"%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
2842
comment_prefix, row[0], row[1]);
2843
check_io(md_result_file);
2845
else if (!ignore_errors)
2847
/* SHOW MASTER STATUS reports nothing and --force is not enabled */
2848
my_printf_error(0, "Error: Binlogging on server not active",
2850
drizzle_free_result(master);
2851
maybe_exit(EX_DRIZZLEERR);
2854
drizzle_free_result(master);
2859
static int do_stop_slave_sql(DRIZZLE *drizzle_con)
2862
/* We need to check if the slave sql is running in the first place */
2863
if (drizzle_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
2867
DRIZZLE_ROW row= drizzle_fetch_row(slave);
2870
/* if SLAVE SQL is not running, we don't stop it */
2871
if (!strcmp(row[11],"No"))
2873
drizzle_free_result(slave);
2874
/* Silently assume that they don't have the slave running */
2879
drizzle_free_result(slave);
2881
/* now, stop slave if running */
2882
if (drizzle_query_with_error_report(drizzle_con, 0, "STOP SLAVE SQL_THREAD"))
2888
static int add_stop_slave(void)
2891
fprintf(md_result_file,
2892
"\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
2893
fprintf(md_result_file, "STOP SLAVE;\n");
2897
static int add_slave_statements(void)
2900
fprintf(md_result_file,
2901
"\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
2902
fprintf(md_result_file, "START SLAVE;\n");
2906
static int do_show_slave_status(DRIZZLE *drizzle_con)
2909
const char *comment_prefix=
2910
(opt_slave_data == DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
2911
if (drizzle_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
2915
/* SHOW SLAVE STATUS reports nothing and --force is not enabled */
2916
my_printf_error(0, "Error: Slave not set up", MYF(0));
2922
DRIZZLE_ROW row= drizzle_fetch_row(slave);
2923
if (row && row[9] && row[21])
2925
/* SHOW MASTER STATUS reports file and position */
2927
fprintf(md_result_file,
2928
"\n--\n-- Position to start replication or point-in-time "
2929
"recovery from (the master of this slave)\n--\n\n");
2931
fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
2933
if (opt_include_master_host_port)
2936
fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
2938
fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
2940
fprintf(md_result_file,
2941
"MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
2943
check_io(md_result_file);
2945
drizzle_free_result(slave);
2950
static int do_start_slave_sql(DRIZZLE *drizzle_con)
2953
/* We need to check if the slave sql is stopped in the first place */
2954
if (drizzle_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
2958
DRIZZLE_ROW row= drizzle_fetch_row(slave);
2961
/* if SLAVE SQL is not running, we don't start it */
2962
if (!strcmp(row[11],"Yes"))
2964
drizzle_free_result(slave);
2965
/* Silently assume that they don't have the slave running */
2970
drizzle_free_result(slave);
2972
/* now, start slave if stopped */
2973
if (drizzle_query_with_error_report(drizzle_con, 0, "START SLAVE"))
2975
my_printf_error(0, "Error: Unable to start slave", MYF(0));
2983
static int do_flush_tables_read_lock(DRIZZLE *drizzle_con)
419
2986
We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
420
2987
will wait but will not stall the whole mysqld, and when the long update is
421
2988
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
2989
FLUSH TABLES is to lower the probability of a stage where both mysqldump
423
2990
and most client connections are stalled. Of course, if a second long
424
2991
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");
2994
( drizzle_query_with_error_report(drizzle_con, 0, "FLUSH TABLES") ||
2995
drizzle_query_with_error_report(drizzle_con, 0,
2996
"FLUSH TABLES WITH READ LOCK") );
3000
static int do_unlock_tables(DRIZZLE *drizzle_con)
3002
return drizzle_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES");
3005
static int get_bin_log_name(DRIZZLE *drizzle_con,
3006
char* buff_log_name, uint buff_len)
3011
if (drizzle_query(drizzle_con, "SHOW MASTER STATUS") ||
3012
!(res= drizzle_store_result(drizzle)))
3015
if (!(row= drizzle_fetch_row(res)))
3017
drizzle_free_result(res);
3021
Only one row is returned, and the first column is the name of the
3024
strmake(buff_log_name, row[0], buff_len - 1);
3026
drizzle_free_result(res);
3030
static int purge_bin_logs_to(DRIZZLE *drizzle_con, char* log_name)
3033
string str= "PURGE BINARY LOGS TO '";
3034
str.append(log_name);
3036
err = drizzle_query_with_error_report(drizzle_con, 0, str.c_str());
3041
static int start_transaction(DRIZZLE *drizzle_con)
3044
We use BEGIN for old servers. --single-transaction --master-data will fail
3045
on old servers, but that's ok as it was already silently broken (it didn't
3046
do a consistent read, so better tell people frankly, with the error).
3048
We want the first consistent read to be used for all tables to dump so we
3049
need the REPEATABLE READ level (not anything lower, for example READ
3050
COMMITTED would give one new consistent read per dumped table).
3052
if ((drizzle_get_server_version(drizzle_con) < 40100) && opt_master_data)
3054
fprintf(stderr, "-- %s: the combination of --single-transaction and "
3055
"--master-data requires a DRIZZLE server version of at least 4.1 "
3056
"(current server's version is %s). %s\n",
3057
ignore_errors ? "Warning" : "Error",
3058
drizzle_con->server_version ? drizzle_con->server_version : "unknown",
3059
ignore_errors ? "Continuing due to --force, backup may not be consistent across all tables!" : "Aborting.");
3061
exit(EX_DRIZZLEERR);
3064
return (drizzle_query_with_error_report(drizzle_con, 0,
3065
"SET SESSION TRANSACTION ISOLATION "
3066
"LEVEL REPEATABLE READ") ||
3067
drizzle_query_with_error_report(drizzle_con, 0,
3068
"START TRANSACTION "
3069
"/*!40100 WITH CONSISTENT SNAPSHOT */"));
3073
static uint32_t find_set(TYPELIB *lib, const char *x, uint length,
3074
char **err_pos, uint *err_len)
3076
const char *end= x + length;
3081
*err_pos= 0; /* No error yet */
3082
while (end > x && my_isspace(charset_info, end[-1]))
3088
const char *start= x;
3091
const char *pos= start;
3094
for (; pos != end && *pos != ','; pos++) ;
3095
var_len= (uint32_t) (pos - start);
3096
strmake(buff, start, min(sizeof(buff), var_len));
3097
find= find_type(buff, lib, var_len);
3100
*err_pos= (char*) start;
3104
found|= ((int64_t) 1 << (find - 1));
3114
/* Print a value with a prefix on file */
3115
static void print_value(FILE *file, DRIZZLE_RES *result, DRIZZLE_ROW row,
3116
const char *prefix, const char *name,
3119
DRIZZLE_FIELD *field;
3120
drizzle_field_seek(result, 0);
3122
for ( ; (field= drizzle_fetch_field(result)) ; row++)
3124
if (!strcmp(field->name,name))
3126
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
3129
fputs(prefix, file);
3131
unescape(file,row[0],(uint) strlen(row[0]));
3133
fputs(row[0], file);
3139
return; /* This shouldn't happen */
3146
Check if we the table is one of the table types that should be ignored:
3147
MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
3148
If the table should be altogether ignored, it returns a true, false if it
3149
should not be ignored. If the user has selected to use INSERT DELAYED, it
3150
sets the value of the bool pointer supports_delayed_inserts to 0 if not
3151
supported, 1 if it is supported.
3155
check_if_ignore_table()
3156
table_name Table name to check
3157
table_type Type of table
3160
drizzle Drizzle connection
3161
verbose Write warning messages
3164
char (bit value) See IGNORE_ values at top
3167
char check_if_ignore_table(const char *table_name, char *table_type)
3169
char result= IGNORE_NONE;
3170
char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
3171
DRIZZLE_RES *res= NULL;
3175
/* Check memory for quote_for_like() */
3176
assert(2*sizeof(table_name) < sizeof(show_name_buff));
3177
snprintf(buff, sizeof(buff), "show table status like %s",
3178
quote_for_like(table_name, show_name_buff));
3179
if (drizzle_query_with_error_report(drizzle, &res, buff))
3181
if (drizzle_errno(drizzle) != ER_PARSE_ERROR)
3182
{ /* If old DRIZZLE version */
3183
verbose_msg("-- Warning: Couldn't get status information for "
3184
"table %s (%s)\n", table_name, drizzle_error(drizzle));
3185
return(result); /* assume table is ok */
3188
if (!(row= drizzle_fetch_row(res)))
3191
"Error: Couldn't read status information for table %s (%s)\n",
3192
table_name, drizzle_error(drizzle));
3193
drizzle_free_result(res);
3194
return(result); /* assume table is ok */
3197
strmake(table_type, "VIEW", NAME_LEN-1);
3201
If the table type matches any of these, we do support delayed inserts.
3202
Note: we do not want to skip dumping this table if if is not one of
3203
these types, but we do want to use delayed inserts in the dump if
3204
the table type is _NOT_ one of these types
3206
strmake(table_type, row[1], NAME_LEN-1);
3209
if (strcmp(table_type,"MyISAM") &&
3210
strcmp(table_type,"ISAM") &&
3211
strcmp(table_type,"ARCHIVE") &&
3212
strcmp(table_type,"HEAP") &&
3213
strcmp(table_type,"MEMORY"))
3214
result= IGNORE_INSERT_DELAYED;
3218
If these two types, we do want to skip dumping the table
3221
(!my_strcasecmp(&my_charset_latin1, table_type, "MRG_MyISAM") ||
3222
!strcmp(table_type,"MRG_ISAM")))
3223
result= IGNORE_DATA;
3225
drizzle_free_result(res);
3231
Get string of comma-separated primary key field names
3234
char *primary_key_fields(const char *table_name)
3235
RETURNS pointer to allocated buffer (must be freed by caller)
3236
table_name quoted table name
3239
Use SHOW KEYS FROM table_name, allocate a buffer to hold the
3240
field names, and then build that string and return the pointer
3243
Returns NULL if there is no PRIMARY or UNIQUE key on the table,
3244
or if there is some failure. It is better to continue to dump
3245
the table unsorted, rather than exit without dumping the data.
3248
static char *primary_key_fields(const char *table_name)
3250
DRIZZLE_RES *res= NULL;
3252
/* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
3253
char show_keys_buff[15 + NAME_LEN * 2 + 3];
3254
uint result_length= 0;
3256
char buff[NAME_LEN * 2 + 3];
3259
snprintf(show_keys_buff, sizeof(show_keys_buff),
3260
"SHOW KEYS FROM %s", table_name);
3261
if (drizzle_query(drizzle, show_keys_buff) ||
3262
!(res= drizzle_store_result(drizzle)))
3264
fprintf(stderr, "Warning: Couldn't read keys from table %s;"
3265
" records are NOT sorted (%s)\n",
3266
table_name, drizzle_error(drizzle));
3267
/* Don't exit, because it's better to print out unsorted records */
3272
* Figure out the length of the ORDER BY clause result.
3273
* Note that SHOW KEYS is ordered: a PRIMARY key is always the first
3274
* row, and UNIQUE keys come before others. So we only need to check
3275
* the first key, not all keys.
3277
if ((row= drizzle_fetch_row(res)) && atoi(row[1]) == 0)
3282
quoted_field= quote_name(row[4], buff, 0);
3283
result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
3284
} while ((row= drizzle_fetch_row(res)) && atoi(row[3]) > 1);
3287
/* Build the ORDER BY clause result */
3291
/* result (terminating \0 is already in result_length) */
3292
result= (char *)my_malloc(result_length + 10, MYF(MY_WME));
3295
fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n");
3298
drizzle_data_seek(res, 0);
3299
row= drizzle_fetch_row(res);
3300
quoted_field= quote_name(row[4], buff, 0);
3301
end= stpcpy(result, quoted_field);
3302
while ((row= drizzle_fetch_row(res)) && atoi(row[3]) > 1)
3304
quoted_field= quote_name(row[4], buff, 0);
3305
end= strxmov(end, ",", quoted_field, NullS);
3311
drizzle_free_result(res);
446
3317
int main(int argc, char **argv)
3319
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();
3321
MY_INIT("mysqldump");
3323
compatible_mode_normal_str[0]= 0;
3324
default_charset= (char *)drizzle_universal_client_charset;
3325
memset(&ignore_table, 0, sizeof(ignore_table));
3327
exit_code= get_options(&argc, &argv);
732
3330
free_resources();
733
3331
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! */
3336
if(!(stderror_file= freopen(log_error_file, "a+", stderr)))
3339
exit(EX_DRIZZLEERR);
3343
if (connect_to_db(current_host, current_user, opt_password))
3346
exit(EX_DRIZZLEERR);
3349
write_header(md_result_file, *argv);
3351
if (opt_slave_data && do_stop_slave_sql(drizzle))
3354
if ((opt_lock_all_tables || opt_master_data) &&
3355
do_flush_tables_read_lock(drizzle))
3357
if (opt_single_transaction && start_transaction(drizzle))
3359
if (opt_delete_master_logs)
3361
if (drizzle_refresh(drizzle, REFRESH_LOG) ||
3362
get_bin_log_name(drizzle, bin_log_name, sizeof(bin_log_name)))
3366
if (opt_lock_all_tables || opt_master_data)
3368
if (flush_logs && drizzle_refresh(drizzle, REFRESH_LOG))
3370
flush_logs= 0; /* not anymore; that would not be sensible */
3372
/* Add 'STOP SLAVE to beginning of dump */
3373
if (opt_slave_apply && add_stop_slave())
3375
if (opt_master_data && do_show_master_status(drizzle))
3377
if (opt_slave_data && do_show_slave_status(drizzle))
3379
if (opt_single_transaction && do_unlock_tables(drizzle)) /* unlock but no commit! */
777
3384
dump_all_databases();
780
if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
3386
else if (argc > 1 && !opt_databases)
782
string database_used= *vm["database-used"].as< vector<string> >().begin();
783
3388
/* 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)
3389
dump_selected_tables(*argv, (argv + 1), (argc - 1));
3393
dump_databases(argv);
3396
/* if --dump-slave , start the slave sql thread */
3397
if (opt_slave_data && do_start_slave_sql(drizzle))
3400
/* add 'START SLAVE' to end of dump */
3401
if (opt_slave_apply && add_slave_statements())
814
3404
/* ensure dumped data flushed */
815
3405
if (md_result_file && fflush(md_result_file))