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
29
#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>
39
37
#include <algorithm>
41
39
#include <drizzled/gettext.h>
42
#include <drizzled/configmake.h>
43
41
#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
43
using namespace std;
52
using namespace drizzled;
53
namespace po= boost::program_options;
58
47
#define EX_DRIZZLEERR 2
48
#define EX_CONSCHECK 3
59
50
#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;
51
#define EX_ILLEGAL_TABLE 6
52
#define EX_TABLE_STATUS 7
54
/* index into 'show fields from table' */
56
#define SHOW_FIELDNAME 0
59
#define SHOW_DEFAULT 4
62
/* Size of buffer for dump's select query */
63
#define QUERY_LENGTH 1536
64
#define DRIZZLE_MAX_LINE_LENGTH 1024*1024L-1025
66
/* ignore table flags */
67
#define IGNORE_NONE 0x00 /* no ignore */
68
#define IGNORE_DATA 0x01 /* don't dump data for this table */
69
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
71
static void add_load_option(string &str, const char *option,
72
const char *option_value);
73
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
74
char **err_pos, uint32_t *err_len);
76
static void field_escape(string &in, const char *from);
77
static bool verbose= false, opt_no_create_info= false, opt_no_data= false,
78
quick= true, extended_insert= true,
79
ignore_errors= false, flush_logs= false,
80
opt_drop= true, opt_keywords= false,
82
opt_delayed= false, create_options= true, opt_quoted= false,
83
opt_databases= false, opt_alldbs= false, opt_create_db= false,
84
opt_lock_all_tables= false,
85
opt_set_charset= false, opt_dump_date= true,
86
opt_autocommit= false, opt_disable_keys= true, opt_xml= false,
88
opt_single_transaction= false, opt_comments= false,
89
opt_compact= false, opt_hex_blob= false,
90
opt_order_by_primary=false, opt_ignore= false,
91
opt_complete_insert= false, opt_drop_database= false,
92
opt_replace_into= false,
95
static bool debug_info_flag= false, debug_check_flag= false;
96
static uint32_t show_progress_size= 0;
97
static uint64_t total_rows= 0;
98
static drizzle_st drizzle;
99
static drizzle_con_st dcon;
86
100
static string insert_pat;
101
static char *opt_password= NULL, *current_user= NULL,
102
*current_host= NULL, *path= NULL, *fields_terminated= NULL,
103
*lines_terminated= NULL, *enclosed= NULL, *opt_enclosed= NULL,
105
*where= NULL, *order_by= NULL,
106
*opt_compatible_mode_str= NULL,
108
static char **defaults_argv= NULL;
109
static char compatible_mode_normal_str[255];
110
static uint32_t opt_compatible_mode= 0;
87
111
static uint32_t opt_drizzle_port= 0;
112
static uint32_t my_end_arg;
88
113
static int first_error= 0;
89
114
static string extended_row;
90
115
FILE *md_result_file= 0;
91
116
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);
119
Constant for detection of default value of default_charset.
120
If default_charset is equal to drizzle_universal_client_charset, then
121
it is the default value which assigned at the very beginning of main().
123
static const char *drizzle_universal_client_charset=
124
DRIZZLE_UNIVERSAL_CLIENT_CHARSET;
125
static char *default_charset;
126
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
128
const char *compatible_mode_names[]=
130
"MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
131
"MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
135
#define MASK_ANSI_QUOTES \
137
(1<<2) | /* POSTGRESQL */\
138
(1<<3) | /* ORACLE */\
139
(1<<4) | /* MSSQL */\
141
(1<<6) | /* MAXDB */\
144
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
145
"", compatible_mode_names, NULL};
149
static struct my_option my_long_options[] =
151
{"all", 'a', "Deprecated. Use --create-options instead.",
152
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
154
{"all-databases", 'A',
155
"Dump all the databases. This will be same as --databases with all databases selected.",
156
(char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
158
{"all-tablespaces", 'Y',
159
"Dump all the tablespaces.",
160
(char**) &opt_alltspcs, (char**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
162
{"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
163
(char**) &opt_drop_database, (char**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
165
{"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
166
(char**) &opt_drop, (char**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
168
{"allow-keywords", OPT_KEYWORDS,
169
"Allow creation of column names that are keywords.", (char**) &opt_keywords,
170
(char**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
171
{"comments", 'i', "Write additional information.",
172
(char**) &opt_comments, (char**) &opt_comments, 0, GET_BOOL, NO_ARG,
174
{"compatible", OPT_COMPATIBLE,
175
"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.",
176
(char**) &opt_compatible_mode_str, (char**) &opt_compatible_mode_str, 0,
177
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
178
{"compact", OPT_COMPACT,
179
"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",
180
(char**) &opt_compact, (char**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
182
{"complete-insert", 'c', "Use complete insert statements.",
183
(char**) &opt_complete_insert, (char**) &opt_complete_insert, 0, GET_BOOL,
184
NO_ARG, 0, 0, 0, 0, 0, 0},
185
{"compress", 'C', "Use compression in server/client protocol.",
186
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
188
{"create-options", OPT_CREATE_OPTIONS,
189
"Include all DRIZZLE specific create options.",
190
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
193
"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.",
194
(char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
196
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
197
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
198
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
199
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
200
(char**) &debug_info_flag, (char**) &debug_info_flag,
201
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
202
{"default-character-set", OPT_DEFAULT_CHARSET,
203
"Set the default character set.", (char**) &default_charset,
204
(char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
205
{"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
206
(char**) &opt_delayed, (char**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
208
{"disable-keys", 'K',
209
"'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will be put in the output.", (char**) &opt_disable_keys,
210
(char**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
211
{"extended-insert", 'e',
212
"Allows utilization of the new, much faster INSERT syntax.",
213
(char**) &extended_insert, (char**) &extended_insert, 0, GET_BOOL, NO_ARG,
215
{"fields-terminated-by", OPT_FTB,
216
"Fields in the textfile are terminated by ...", (char**) &fields_terminated,
217
(char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
218
{"fields-enclosed-by", OPT_ENC,
219
"Fields in the importfile are enclosed by ...", (char**) &enclosed,
220
(char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
221
{"fields-optionally-enclosed-by", OPT_O_ENC,
222
"Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
223
(char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
224
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
225
(char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
226
{"flush-logs", 'F', "Flush logs file in server before starting dump. "
227
"Note that if you dump many databases at once (using the option "
228
"--databases= or --all-databases), the logs will be flushed for "
229
"each database dumped. The exception is when using --lock-all-tables "
230
"in this case the logs will be flushed only once, corresponding "
231
"to the moment all tables are locked. So if you want your dump and "
232
"the log flush to happen at the same exact moment you should use "
233
"--lock-all-tables or --flush-logs",
234
(char**) &flush_logs, (char**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
236
{"force", 'f', "Continue even if we get an sql-error.",
237
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG,
239
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
240
NO_ARG, 0, 0, 0, 0, 0, 0},
241
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
242
"VARBINARY, BLOB) in hexadecimal format.",
243
(char**) &opt_hex_blob, (char**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
244
{"host", 'h', "Connect to host.", (char**) ¤t_host,
245
(char**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
246
{"ignore-table", OPT_IGNORE_TABLE,
247
"Do not dump the specified table. To specify more than one table to ignore, "
248
"use the directive multiple times, once for each table. Each table must "
249
"be specified with both database and table names, e.g. --ignore-table=database.table",
250
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
251
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
252
(char**) &opt_ignore, (char**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
254
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
255
(char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
256
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
257
{"lock-all-tables", 'x', "Locks all tables across all databases. This "
258
"is achieved by taking a global read lock for the duration of the whole "
259
"dump. Automatically turns --single-transaction and --lock-tables off.",
260
(char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
262
{"no-autocommit", OPT_AUTOCOMMIT,
263
"Wrap tables with autocommit/commit statements.",
264
(char**) &opt_autocommit, (char**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
266
{"no-create-db", 'n',
267
"'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.}.",
268
(char**) &opt_create_db, (char**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
270
{"no-create-info", 't', "Don't write table creation info.",
271
(char**) &opt_no_create_info, (char**) &opt_no_create_info, 0, GET_BOOL,
272
NO_ARG, 0, 0, 0, 0, 0, 0},
273
{"no-data", 'd', "No row information.", (char**) &opt_no_data,
274
(char**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
275
{"no-set-names", 'N',
276
"Deprecated. Use --skip-set-charset instead.",
277
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
278
{"opt", OPT_OPTIMIZE,
279
"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.",
280
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
281
{"order-by-primary", OPT_ORDER_BY_PRIMARY,
282
"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.",
283
(char**) &opt_order_by_primary, (char**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
285
"Password to use when connecting to server. If password is not given it's solicited on the tty.",
286
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
287
{"port", 'p', "Port number to use for connection.",
288
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
289
{"quick", 'q', "Don't buffer query, dump directly to stdout.",
290
(char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
291
{"quote-names",'Q', "Quote table and column names with backticks (`).",
292
(char**) &opt_quoted, (char**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
294
{"replace", OPT_DRIZZLE_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
295
(char**) &opt_replace_into, (char**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
298
"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).",
299
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
300
{"routines", 'R', "Dump stored routines (functions and procedures).",
301
(char**) &opt_routines, (char**) &opt_routines, 0, GET_BOOL,
302
NO_ARG, 0, 0, 0, 0, 0, 0},
303
{"single-transaction", OPT_TRANSACTION,
304
"Creates a consistent snapshot by dumping all tables in a single "
305
"transaction. Works ONLY for tables stored in storage engines which "
306
"support multiversioning (currently only InnoDB does); the dump is NOT "
307
"guaranteed to be consistent for other storage engines. "
308
"While a --single-transaction dump is in process, to ensure a valid "
309
"dump file (correct table contents), no other "
310
"connection should use the following statements: ALTER TABLE, DROP "
311
"TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
312
"isolated from them. Option automatically turns off --lock-tables.",
313
(char**) &opt_single_transaction, (char**) &opt_single_transaction, 0,
314
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
315
{"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
316
(char**) &opt_dump_date, (char**) &opt_dump_date, 0,
317
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
318
{"skip-opt", OPT_SKIP_OPTIMIZATION,
319
"Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
320
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
322
"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.",
323
(char**) &path, (char**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
324
{"tables", OPT_TABLES, "Overrides option --databases (-B).",
325
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
326
{"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of rows before each output progress report (requires --verbose)."),
327
(char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
328
10000, 0, 0, 0, 0, 0},
329
#ifndef DONT_ALLOW_USER_CHANGE
330
{"user", 'u', "User for login if not current user.",
331
(char**) ¤t_user, (char**) ¤t_user, 0, GET_STR, REQUIRED_ARG,
334
{"verbose", 'v', "Print info about the various stages.",
335
(char**) &verbose, (char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
336
{"version",'V', "Output version information and exit.", 0, 0, 0,
337
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
338
{"where", 'w', "Dump only selected records; QUOTES mandatory!",
339
(char**) &where, (char**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
340
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
341
NO_ARG, 0, 0, 0, 0, 0, 0},
342
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
345
static const char *load_default_groups[]= { "drizzledump","client",0 };
347
static void maybe_exit(int error);
124
348
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);
349
static void maybe_die(int error, const char* reason, ...);
350
static void write_header(FILE *sql_file, char *db_name);
351
static void print_value(FILE *file, drizzle_result_st *result,
352
drizzle_row_t row, const char *prefix, const char *name,
354
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row,
356
static int dump_selected_tables(char *db, char **table_names, int tables);
357
static int dump_all_tables_in_db(char *db);
358
static int init_dumping_tables(char *);
359
static int init_dumping(char *, int init_func(char*));
360
static int dump_databases(char **);
128
361
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;
362
static char *quote_name(const char *name, char *buff, bool force);
363
char check_if_ignore_table(const char *table_name, char *table_type);
364
static char *primary_key_fields(const char *table_name);
367
Print the supplied message if in verbose mode
372
... variable number of parameters
374
static void verbose_msg(const char *fmt, ...)
383
vfprintf(stderr, fmt, args);
221
390
exit with message if ferror(file)
228
397
static void check_io(FILE *file)
312
796
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
315
fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
799
fprintf(stderr, "%s: %s\n", my_progname, buffer);
318
802
ignore_errors= 0; /* force the exit */
319
803
maybe_exit(error_num);
808
Prints out an error message and maybe kills the process.
812
error_num - process return value
813
fmt_reason - a format string for use by vsnprintf.
814
... - variable arguments for above fmt_reason string
817
This call prints out the formatted error message to stderr and then
818
terminates the process, unless the --force command line option is used.
820
This call should be used for non-fatal errors (such as database
821
errors) that the code may still be able to continue to the next unit
825
static void maybe_die(int error_num, const char* fmt_reason, ...)
829
va_start(args,fmt_reason);
830
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
833
fprintf(stderr, "%s: %s\n", my_progname, buffer);
836
maybe_exit(error_num);
842
Sends a query to server, optionally reads result, prints error message if
846
drizzleclient_query_with_error_report()
847
drizzle_con connection to use
848
res if non zero, result will be put there with
849
drizzleclient_store_result()
850
query query to send to server
853
0 query sending and (if res!=0) result reading went ok
857
static int drizzleclient_query_with_error_report(drizzle_con_st *con,
858
drizzle_result_st *result,
859
const char *query_str,
862
drizzle_return_t ret;
864
if (drizzle_query_str(con, result, query_str, &ret) == NULL ||
865
ret != DRIZZLE_RETURN_OK)
867
if (ret == DRIZZLE_RETURN_ERROR_CODE)
869
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
870
query_str, drizzle_result_error(result),
871
drizzle_result_error_code(result));
872
drizzle_result_free(result);
876
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
877
query_str, drizzle_con_error(con), ret);
883
ret= drizzle_column_buffer(result);
885
ret= drizzle_result_buffer(result);
886
if (ret != DRIZZLE_RETURN_OK)
888
drizzle_result_free(result);
889
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
890
query_str, drizzle_con_error(con), ret);
898
Open a new .sql file to dump the table or view into
901
open_sql_file_for_table
902
name name of the table or view
905
0 Failed to open file
906
> 0 Handle of the open file
908
static FILE* open_sql_file_for_table(const char* table)
911
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
912
convert_dirname(tmp_path,path,NULL);
913
res= fopen(fn_format(filename, table, tmp_path, ".sql", 4), "w");
322
919
static void free_resources(void)
324
921
if (md_result_file && md_result_file != stdout)
325
922
fclose(md_result_file);
326
opt_password.erase();
924
if (hash_inited(&ignore_table))
925
hash_free(&ignore_table);
927
free_defaults(defaults_argv);
330
void maybe_exit(int error)
932
static void maybe_exit(int error)
332
934
if (!first_error)
333
935
first_error= error;
334
936
if (ignore_errors)
336
delete db_connection;
337
delete destination_connection;
938
drizzle_con_free(&dcon);
939
drizzle_free(&drizzle);
338
940
free_resources();
946
db_connect -- connects to the host and selects DB.
949
static int connect_to_db(char *host, char *user,char *passwd)
951
drizzle_return_t ret;
953
verbose_msg(_("-- Connecting to %s...\n"), host ? host : "localhost");
954
drizzle_create(&drizzle);
955
drizzle_con_create(&drizzle, &dcon);
956
drizzle_con_set_tcp(&dcon, host, opt_drizzle_port);
957
drizzle_con_set_auth(&dcon, user, passwd);
958
ret= drizzle_con_connect(&dcon);
959
if (ret != DRIZZLE_RETURN_OK)
961
DB_error(NULL, ret, "when trying to connect");
966
} /* connect_to_db */
970
** dbDisconnect -- disconnects from the host.
972
static void dbDisconnect(char *host)
974
verbose_msg(_("-- Disconnecting from %s...\n"), host ? host : "localhost");
975
drizzle_con_free(&dcon);
976
drizzle_free(&drizzle);
980
static void unescape(FILE *file,char *pos,uint32_t length)
984
if (!(tmp=(char*) malloc(length*2+1)))
985
die(EX_DRIZZLEERR, _("Couldn't allocate memory"));
987
drizzle_escape_string(tmp, pos, length);
997
static bool test_if_special_chars(const char *str)
999
for ( ; *str ; str++)
1000
if (!my_isvar(charset_info,*str) && *str != '$')
1003
} /* test_if_special_chars */
1008
quote_name(name, buff, force)
1010
Quotes char string, taking into account compatible mode
1014
name Unquoted string containing that which will be quoted
1015
buff The buffer that contains the quoted value, also returned
1016
force Flag to make it ignore 'test_if_special_chars'
1023
static char *quote_name(const char *name, char *buff, bool force)
1028
if (!force && !opt_quoted && !test_if_special_chars(name))
1029
return (char*) name;
1044
Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
1048
name name of the table
1049
buff quoted name of the table
1052
Quote \, _, ' and % characters
1054
Note: Because DRIZZLE uses the C escape syntax in strings
1055
(for example, '\n' to represent newline), you must double
1056
any '\' that you use in your LIKE strings. For example, to
1057
search for '\n', specify it as '\\n'. To search for '\', specify
1058
it as '\\\\' (the backslashes are stripped once by the parser
1059
and another time when the pattern match is done, leaving a
1060
single backslash to be matched).
1062
Example: "t\1" => "t\\\\1"
1065
static char *quote_for_like(const char *name, char *buff)
1077
else if (*name == '\'' || *name == '_' || *name == '%')
1088
Quote and print a string.
1092
xml_file - output file
1093
str - string to print
1097
Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1100
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
1104
for (end= str + len; str != end; str++)
1108
fputs("<", xml_file);
1111
fputs(">", xml_file);
1114
fputs("&", xml_file);
1117
fputs(""", xml_file);
1120
fputc(*str, xml_file);
1129
Print xml tag. Optionally add attribute(s).
1132
print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
1133
..., attribute_name_n, attribute_value_n, NULL)
1134
xml_file - output file
1135
sbeg - line beginning
1136
line_end - line ending
1137
tag_name - XML tag name.
1138
first_attribute_name - tag and first attribute
1139
first_attribute_value - (Implied) value of first attribute
1140
attribute_name_n - attribute n
1141
attribute_value_n - value of attribute n
1144
Print XML tag with any number of attribute="value" pairs to the xml_file.
1147
sbeg<tag_name first_attribute_name="first_attribute_value" ...
1148
attribute_name_n="attribute_value_n">send
1150
Additional arguments must be present in attribute/value pairs.
1151
The last argument should be the null character pointer.
1152
All attribute_value arguments MUST be NULL terminated strings.
1153
All attribute_value arguments will be quoted before output.
1156
static void print_xml_tag(FILE * xml_file, const char* sbeg,
1157
const char* line_end,
1158
const char* tag_name,
1159
const char* first_attribute_name, ...)
1162
const char *attribute_name, *attribute_value;
1164
fputs(sbeg, xml_file);
1165
fputc('<', xml_file);
1166
fputs(tag_name, xml_file);
1168
va_start(arg_list, first_attribute_name);
1169
attribute_name= first_attribute_name;
1170
while (attribute_name != NULL)
1172
attribute_value= va_arg(arg_list, char *);
1173
assert(attribute_value != NULL);
1175
fputc(' ', xml_file);
1176
fputs(attribute_name, xml_file);
1177
fputc('\"', xml_file);
1179
print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
1180
fputc('\"', xml_file);
1182
attribute_name= va_arg(arg_list, char *);
1186
fputc('>', xml_file);
1187
fputs(line_end, xml_file);
1193
Print xml tag with for a field that is null
1196
print_xml_null_tag()
1197
xml_file - output file
1198
sbeg - line beginning
1199
stag_atr - tag and attribute
1200
sval - value of attribute
1201
line_end - line ending
1204
Print tag with one attribute to the xml_file. Format is:
1205
<stag_atr="sval" xsi:nil="true"/>
1207
sval MUST be a NULL terminated string.
1208
sval string will be qouted before output.
1211
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
1212
const char* stag_atr, const char* sval,
1213
const char* line_end)
1215
fputs(sbeg, xml_file);
1216
fputs("<", xml_file);
1217
fputs(stag_atr, xml_file);
1218
fputs("\"", xml_file);
1219
print_quoted_xml(xml_file, sval, strlen(sval));
1220
fputs("\" xsi:nil=\"true\" />", xml_file);
1221
fputs(line_end, xml_file);
1227
Print xml tag with many attributes.
1231
xml_file - output file
1232
row_name - xml tag name
1233
tableRes - query result
1237
Print tag with many attribute to the xml_file. Format is:
1238
\t\t<row_name Atr1="Val1" Atr2="Val2"... />
1240
All atributes and values will be quoted before output.
1243
static void print_xml_row(FILE *xml_file, const char *row_name,
1244
drizzle_result_st *tableRes, drizzle_row_t *row)
1247
drizzle_column_st *column;
1248
size_t *lengths= drizzle_row_field_sizes(tableRes);
1250
fprintf(xml_file, "\t\t<%s", row_name);
1252
drizzle_column_seek(tableRes, 0);
1253
for (i= 0; (column= drizzle_column_next(tableRes)); i++)
1257
fputc(' ', xml_file);
1258
print_quoted_xml(xml_file, drizzle_column_name(column),
1259
strlen(drizzle_column_name(column)));
1260
fputs("=\"", xml_file);
1261
print_quoted_xml(xml_file, (*row)[i], lengths[i]);
1262
fputc('"', xml_file);
1266
fputs(" />\n", xml_file);
1272
Print hex value for blob data.
1276
output_file - output file
1277
str - string to print
1281
Print hex value for blob data.
1284
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
1286
/* sakaik got the idea to to provide blob's in hex notation. */
1287
const char *ptr= str, *end= ptr + len;
1288
for (; ptr < end ; ptr++)
1289
fprintf(output_file, "%02X", *((unsigned char *)ptr));
1290
check_io(output_file);
1294
get_table_structure -- retrievs database structure, prints out corresponding
1295
CREATE statement and fills out insert_pat if the table is the type we will
1301
table_type - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
1302
ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1303
num_fields - number of fields in the table
1306
true if success, false if error
1309
static bool get_table_structure(char *table, char *db, char *table_type,
1310
char *ignore_flag, uint64_t *num_fields)
1312
bool init=0, delayed, write_data, complete_insert;
1313
char *result_table, *opt_quoted_table;
1314
const char *insert_option;
1315
char name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE+3];
1316
char table_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+3];
1317
char table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3];
1318
char query_buff[QUERY_LENGTH];
1319
FILE *sql_file= md_result_file;
1320
drizzle_result_st result;
1323
*ignore_flag= check_if_ignore_table(table, table_type);
1325
delayed= opt_delayed;
1326
if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
1329
verbose_msg(_("-- Warning: Unable to use delayed inserts for table '%s' "
1330
"because it's of type %s\n"), table, table_type);
1334
if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1336
complete_insert= opt_complete_insert;
1340
insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
1341
delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
1343
verbose_msg(_("-- Retrieving table structure for table %s...\n"), table);
1345
result_table= quote_name(table, table_buff, 1);
1346
opt_quoted_table= quote_name(table, table_buff2, 0);
1348
if (opt_order_by_primary)
1351
order_by= primary_key_fields(result_table);
1356
/* using SHOW CREATE statement */
1357
if (!opt_no_create_info)
1359
/* Make an sql-file, if path was given iow. option -T was given */
1360
char buff[20+FN_REFLEN];
1361
const drizzle_column_st *column;
1363
snprintf(buff, sizeof(buff), "show create table %s", result_table);
1365
if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1370
if (!(sql_file= open_sql_file_for_table(table)))
1372
drizzle_result_free(&result);
1376
write_header(sql_file, db);
1378
if (!opt_xml && opt_comments)
1380
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1387
Even if the "table" is a view, we do a DROP TABLE here.
1389
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
1393
column= drizzle_column_index(&result, 0);
1395
row= drizzle_row_next(&result);
1397
fprintf(sql_file, "%s;\n", row[1]);
1400
drizzle_result_free(&result);
1403
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1406
if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
1414
If write_data is true, then we build up insert statements for
1415
the table's data. Note: in subsequent lines of code, this test
1416
will have to be performed each time we are appending to
1421
if (opt_replace_into)
1422
insert_pat.append("REPLACE ");
1424
insert_pat.append("INSERT ");
1425
insert_pat.append(insert_option);
1426
insert_pat.append("INTO ");
1427
insert_pat.append(opt_quoted_table);
1428
if (complete_insert)
1430
insert_pat.append(" (");
1434
insert_pat.append(" VALUES ");
1435
if (!extended_insert)
1436
insert_pat.append("(");
1440
while ((row= drizzle_row_next(&result)))
1442
if (complete_insert)
1446
insert_pat.append(", ");
1449
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1452
*num_fields= drizzle_result_row_count(&result);
1453
drizzle_result_free(&result);
1457
verbose_msg(_("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n"),
1458
my_progname, drizzle_con_error(&dcon));
1460
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1462
if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
1465
/* Make an sql-file, if path was given iow. option -T was given */
1466
if (!opt_no_create_info)
1470
if (!(sql_file= open_sql_file_for_table(table)))
1472
drizzle_result_free(&result);
1475
write_header(sql_file, db);
1477
if (!opt_xml && opt_comments)
1478
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1481
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1483
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
1485
print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
1492
if (opt_replace_into)
1493
insert_pat.append("REPLACE ");
1495
insert_pat.append("INSERT ");
1496
insert_pat.append(insert_option);
1497
insert_pat.append("INTO ");
1498
insert_pat.append(result_table);
1499
if (complete_insert)
1500
insert_pat.append(" (");
1503
insert_pat.append(" VALUES ");
1504
if (!extended_insert)
1505
insert_pat.append("(");
1509
while ((row= drizzle_row_next(&result)))
1511
size_t *lengths= drizzle_row_field_sizes(&result);
1514
if (!opt_xml && !opt_no_create_info)
1516
fputs(",\n",sql_file);
1519
if (complete_insert)
1520
insert_pat.append(", ");
1523
if (complete_insert)
1524
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1525
if (!opt_no_create_info)
1529
print_xml_row(sql_file, "field", &result, &row);
1534
fprintf(sql_file, " %s.%s %s", result_table,
1535
quote_name(row[SHOW_FIELDNAME],name_buff, 0),
1538
fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
1541
if (row[SHOW_DEFAULT])
1543
fputs(" DEFAULT ", sql_file);
1544
unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1546
if (!row[SHOW_NULL][0])
1547
fputs(" NOT NULL", sql_file);
1548
if (row[SHOW_EXTRA][0])
1549
fprintf(sql_file, " %s",row[SHOW_EXTRA]);
1553
*num_fields= drizzle_result_row_count(&result);
1554
drizzle_result_free(&result);
1556
if (!opt_no_create_info)
1558
/* Make an sql-file, if path was given iow. option -T was given */
1559
char buff[20+FN_REFLEN];
1560
uint32_t keynr,primary_key;
1561
snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1562
if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1564
fprintf(stderr, _("%s: Can't get keys for table %s\n"),
1565
my_progname, result_table);
1571
/* Find first which key is primary key */
1573
primary_key=INT_MAX;
1574
while ((row= drizzle_row_next(&result)))
1576
if (atoi(row[3]) == 1)
1579
#ifdef FORCE_PRIMARY_KEY
1580
if (atoi(row[1]) == 0 && primary_key == INT_MAX)
1583
if (!strcmp(row[2],"PRIMARY"))
1590
drizzle_row_seek(&result,0);
1592
while ((row= drizzle_row_next(&result)))
1596
print_xml_row(sql_file, "key", &result, &row);
1600
if (atoi(row[3]) == 1)
1603
putc(')', sql_file);
1604
if (atoi(row[1])) /* Test if duplicate key */
1605
/* Duplicate allowed */
1606
fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0));
1607
else if (keynr == primary_key)
1608
fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
1610
fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
1614
putc(',', sql_file);
1615
fputs(quote_name(row[4], name_buff, 0), sql_file);
1617
fprintf(sql_file, " (%s)",row[7]); /* Sub key */
1620
drizzle_result_free(&result);
1624
putc(')', sql_file);
1625
fputs("\n)",sql_file);
1628
/* Get DRIZZLE specific create options */
1631
char show_name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+2+24];
1633
/* Check memory for quote_for_like() */
1634
snprintf(buff, sizeof(buff), "show table status like %s",
1635
quote_for_like(table, show_name_buff));
1637
if (!drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1639
if (!(row= drizzle_row_next(&result)))
1642
_("Error: Couldn't read status information for table %s\n"),
1648
print_xml_row(sql_file, "options", &result, &row);
1651
fputs("/*!",sql_file);
1652
print_value(sql_file,&result,row,"engine=","Engine",0);
1653
print_value(sql_file,&result,row,"","Create_options",0);
1654
print_value(sql_file,&result,row,"comment=","Comment",1);
1656
fputs(" */",sql_file);
1660
drizzle_result_free(&result);
1664
fputs(";\n", sql_file);
1666
fputs("\t</table_structure>\n", sql_file);
1670
if (complete_insert) {
1671
insert_pat.append(") VALUES ");
1672
if (!extended_insert)
1673
insert_pat.append("(");
1675
if (sql_file != md_result_file)
1677
fputs("\n", sql_file);
1678
write_footer(sql_file);
1682
} /* get_table_structure */
1684
static void add_load_option(string &str, const char *option,
1685
const char *option_value)
1689
/* Null value means we don't add this option. */
1695
if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
1697
/* It's a hex constant, don't escape */
1698
str.append(option_value);
1702
/* char constant; escape */
1703
field_escape(str, option_value);
1709
Allow the user to specify field terminator strings like:
1710
"'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
1711
This is done by doubling ' and add a end -\ if needed to avoid
1712
syntax errors from the SQL parser.
1715
static void field_escape(string &in, const char *from)
1717
uint32_t end_backslashes= 0;
1726
end_backslashes^=1; /* find odd number of backslashes */
1729
if (*from == '\'' && !end_backslashes)
1731
/* We want a duplicate of "'" for DRIZZLE */
1738
/* Add missing backslashes if user has specified odd number of backs.*/
1739
if (end_backslashes)
1752
dump_table saves database contents as a series of INSERT statements.
1763
static void dump_table(char *table, char *db)
1766
char table_buff[DRIZZLE_MAX_TABLE_SIZE+3];
1767
string query_string;
1768
char table_type[DRIZZLE_MAX_TABLE_SIZE];
1769
char *result_table, table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3], *opt_quoted_table;
1771
uint32_t rownr, row_break, total_length, init_length;
1772
uint64_t num_fields= 0;
1773
drizzle_return_t ret;
1774
drizzle_result_st result;
1775
drizzle_column_st *column;
1780
Make sure you get the create table info before the following check for
1781
--no-data flag below. Otherwise, the create table info won't be printed.
1783
if (!get_table_structure(table, db, table_type, &ignore_flag, &num_fields))
1785
maybe_die(EX_TABLE_STATUS, _("Error retrieving table structure for table: \"%s\""), table);
1789
/* Check --no-data flag */
1792
verbose_msg(_("-- Skipping dump data for table '%s', --no-data was used\n"),
1798
If the table type is a merge table or any type that has to be
1799
_completely_ ignored and no data dumped
1801
if (ignore_flag & IGNORE_DATA)
1803
verbose_msg(_("-- Warning: Skipping data for table '%s' because " \
1804
"it's of type %s\n"), table, table_type);
1807
/* Check that there are any fields in the table */
1808
if (num_fields == 0)
1810
verbose_msg(_("-- Skipping dump data for table '%s', it has no fields\n"),
1815
result_table= quote_name(table,table_buff, 1);
1816
opt_quoted_table= quote_name(table, table_buff2, 0);
1818
verbose_msg(_("-- Sending SELECT query...\n"));
1820
query_string.clear();
1821
query_string.reserve(1024);
1825
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
1828
Convert the path to native os format
1829
and resolve to the full filepath.
1831
convert_dirname(tmp_path,path,NULL);
1832
my_load_path(tmp_path, tmp_path, NULL);
1833
fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
1835
/* Must delete the file that 'INTO OUTFILE' will write to */
1836
my_delete(filename, MYF(0));
1838
/* now build the query string */
1840
query_string.append( "SELECT * INTO OUTFILE '");
1841
query_string.append( filename);
1842
query_string.append( "'");
1844
if (fields_terminated || enclosed || opt_enclosed || escaped)
1845
query_string.append( " FIELDS");
1847
add_load_option(query_string, " TERMINATED BY ", fields_terminated);
1848
add_load_option(query_string, " ENCLOSED BY ", enclosed);
1849
add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
1850
add_load_option(query_string, " ESCAPED BY ", escaped);
1851
add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
1853
query_string.append( " FROM ");
1854
query_string.append( result_table);
1858
query_string.append( " WHERE ");
1859
query_string.append( where);
1864
query_string.append( " ORDER BY ");
1865
query_string.append( order_by);
1868
if (drizzle_query(&dcon, &result, query_string.c_str(),
1869
query_string.length(), &ret) == NULL ||
1870
ret != DRIZZLE_RETURN_OK)
1872
DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
1876
drizzle_result_free(&result);
1880
if (!opt_xml && opt_comments)
1882
fprintf(md_result_file,_("\n--\n-- Dumping data for table %s\n--\n"),
1884
check_io(md_result_file);
1887
query_string.append( "SELECT * FROM ");
1888
query_string.append( result_table);
1892
if (!opt_xml && opt_comments)
1894
fprintf(md_result_file, "-- WHERE: %s\n", where);
1895
check_io(md_result_file);
1898
query_string.append( " WHERE ");
1899
query_string.append( where);
1903
if (!opt_xml && opt_comments)
1905
fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
1906
check_io(md_result_file);
1908
query_string.append( " ORDER BY ");
1909
query_string.append( order_by);
1912
if (!opt_xml && !opt_compact)
1914
fputs("\n", md_result_file);
1915
check_io(md_result_file);
1917
if (drizzleclient_query_with_error_report(&dcon, &result,
1918
query_string.c_str(), quick))
1923
verbose_msg(_("-- Retrieving rows...\n"));
1924
if (drizzle_result_column_count(&result) != num_fields)
1926
fprintf(stderr,_("%s: Error in field count for table: %s ! Aborting.\n"),
1927
my_progname, result_table);
1928
error= EX_CONSCHECK;
1929
drizzle_result_free(&result);
1933
/* Moved disable keys to after lock per bug 15977 */
1934
if (opt_disable_keys)
1936
fprintf(md_result_file, "ALTER TABLE %s DISABLE KEYS;\n",
1938
check_io(md_result_file);
1941
total_length= DRIZZLE_MAX_LINE_LENGTH; /* Force row break */
1944
init_length=(uint32_t) insert_pat.length()+4;
1946
print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
1950
fprintf(md_result_file, "set autocommit=0;\n");
1951
check_io(md_result_file);
1964
drizzle_row_free(&result, row);
1966
row= drizzle_row_buffer(&result, &ret);
1967
if (ret != DRIZZLE_RETURN_OK)
1970
_("%s: Error reading rows for table: %s (%d:%s) ! Aborting.\n"),
1971
my_progname, result_table, ret, drizzle_con_error(&dcon));
1972
drizzle_result_free(&result);
1977
row= drizzle_row_next(&result);
1982
lengths= drizzle_row_field_sizes(&result);
1985
if ((rownr % show_progress_size) == 0)
1987
verbose_msg(_("-- %"PRIu32" of ~%"PRIu64" rows dumped for table %s\n"), rownr, total_rows, opt_quoted_table);
1989
if (!extended_insert && !opt_xml)
1991
fputs(insert_pat.c_str(),md_result_file);
1992
check_io(md_result_file);
1994
drizzle_column_seek(&result,0);
1998
fputs("\t<row>\n", md_result_file);
1999
check_io(md_result_file);
2002
for (i= 0; i < drizzle_result_column_count(&result); i++)
2005
uint32_t length= lengths[i];
2007
if (!(column= drizzle_column_next(&result)))
2009
_("Not enough fields from table %s! Aborting.\n"),
2013
63 is my_charset_bin. If charsetnr is not 63,
2014
we have not a BLOB but a TEXT column.
2015
we'll dump in hex only BLOB columns.
2017
is_blob= (opt_hex_blob && drizzle_column_charset(column) == 63 &&
2018
(drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_VARCHAR ||
2019
drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_BLOB)) ? 1 : 0;
2020
if (extended_insert && !opt_xml)
2024
extended_row.clear();
2025
extended_row.append("(");
2028
extended_row.append(",");
2034
if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
2037
"length * 2 + 2" is OK for both HEX and non-HEX modes:
2038
- In HEX mode we need exactly 2 bytes per character
2039
plus 2 bytes for '0x' prefix.
2040
- In non-HEX mode we need up to 2 bytes per character,
2041
plus 2 bytes for leading and trailing '\'' characters.
2042
Also we need to reserve 1 byte for terminating '\0'.
2044
char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
2045
memset(tmp_str, '\0', length * 2 + 2 + 1);
2046
if (opt_hex_blob && is_blob)
2048
extended_row.append("0x");
2049
drizzle_hex_string(tmp_str, row[i], length);
2050
extended_row.append(tmp_str);
2054
extended_row.append("'");
2055
drizzle_escape_string(tmp_str, row[i],length);
2056
extended_row.append(tmp_str);
2057
extended_row.append("'");
2063
/* change any strings ("inf", "-inf", "nan") into NULL */
2065
if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
2066
my_isalpha(charset_info, ptr[1])))
2067
extended_row.append( "NULL");
2070
extended_row.append( ptr);
2075
extended_row.append("''");
2078
extended_row.append("NULL");
2084
fputc(',', md_result_file);
2085
check_io(md_result_file);
2089
if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
2093
if (opt_hex_blob && is_blob && length)
2095
/* Define xsi:type="xs:hexBinary" for hex encoded data */
2096
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2097
drizzle_column_name(column), "xsi:type=", "xs:hexBinary", NULL);
2098
print_blob_as_hex(md_result_file, row[i], length);
2102
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2103
drizzle_column_name(column), NULL);
2104
print_quoted_xml(md_result_file, row[i], length);
2106
fputs("</field>\n", md_result_file);
2108
else if (opt_hex_blob && is_blob && length)
2110
fputs("0x", md_result_file);
2111
print_blob_as_hex(md_result_file, row[i], length);
2114
unescape(md_result_file, row[i], length);
2118
/* change any strings ("inf", "-inf", "nan") into NULL */
2122
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2123
drizzle_column_name(column), NULL);
2124
fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
2126
fputs("</field>\n", md_result_file);
2128
else if (my_isalpha(charset_info, *ptr) ||
2129
(*ptr == '-' && my_isalpha(charset_info, ptr[1])))
2130
fputs("NULL", md_result_file);
2132
fputs(ptr, md_result_file);
2137
/* The field value is NULL */
2139
fputs("NULL", md_result_file);
2141
print_xml_null_tag(md_result_file, "\t\t", "field name=",
2142
drizzle_column_name(column), "\n");
2144
check_io(md_result_file);
2150
fputs("\t</row>\n", md_result_file);
2151
check_io(md_result_file);
2154
if (extended_insert)
2156
uint32_t row_length;
2157
extended_row.append(")");
2158
row_length= 2 + extended_row.length();
2159
if (total_length + row_length < DRIZZLE_MAX_LINE_LENGTH)
2161
total_length+= row_length;
2162
fputc(',',md_result_file); /* Always row break */
2163
fputs(extended_row.c_str(),md_result_file);
2168
fputs(";\n", md_result_file);
2169
row_break=1; /* This is first row */
2171
fputs(insert_pat.c_str(),md_result_file);
2172
fputs(extended_row.c_str(),md_result_file);
2173
total_length= row_length+init_length;
2175
check_io(md_result_file);
2179
fputs(");\n", md_result_file);
2180
check_io(md_result_file);
2184
/* XML - close table tag and supress regular output */
2186
fputs("\t</table_data>\n", md_result_file);
2187
else if (extended_insert && row_break)
2188
fputs(";\n", md_result_file); /* If not empty table */
2189
fflush(md_result_file);
2190
check_io(md_result_file);
2192
/* Moved enable keys to before unlock per bug 15977 */
2193
if (opt_disable_keys)
2195
fprintf(md_result_file,"ALTER TABLE %s ENABLE KEYS;\n",
2197
check_io(md_result_file);
2201
fprintf(md_result_file, "commit;\n");
2202
check_io(md_result_file);
2204
drizzle_result_free(&result);
2214
static char *getTableName(int reset)
2216
static drizzle_result_st result;
2217
static bool have_result= false;
2222
if (drizzleclient_query_with_error_report(&dcon, &result, "SHOW TABLES", false))
2227
if ((row= drizzle_row_next(&result)))
2231
drizzle_row_seek(&result, 0);
2234
drizzle_result_free(&result);
2238
} /* getTableName */
342
2241
static int dump_all_databases()
344
2243
drizzle_row_t row;
345
drizzle_result_st *tableres;
2244
drizzle_result_st 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)))
2247
if (drizzleclient_query_with_error_report(&dcon, &tableres, "SHOW DATABASES", false))
2249
while ((row= drizzle_row_next(&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);
2251
if (dump_all_tables_in_db(row[0]))
371
db_connection->freeResult(tableres);
2254
drizzle_result_free(&tableres);
374
2257
/* dump_all_databases */
377
static int dump_databases(const vector<string> &db_names)
2260
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)
2266
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);
2268
if (dump_all_tables_in_db(*db))
393
2272
} /* 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);
2276
Table Specific database initalization.
2280
qdatabase quoted name of the database
2287
int init_dumping_tables(char *qdatabase)
2293
drizzle_result_st result;
2294
drizzle_return_t ret;
2296
snprintf(qbuf, sizeof(qbuf),
2297
"SHOW CREATE DATABASE IF NOT EXISTS %s",
2300
if (drizzle_query_str(&dcon, &result, qbuf, &ret) == NULL ||
2301
ret != DRIZZLE_RETURN_OK)
2303
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2304
drizzle_result_free(&result);
2306
/* Old server version, dump generic CREATE DATABASE */
2307
if (opt_drop_database)
2308
fprintf(md_result_file,
2309
"\nDROP DATABASE IF EXISTS %s;\n",
2311
fprintf(md_result_file,
2312
"\nCREATE DATABASE IF NOT EXISTS %s;\n",
2317
if (drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
2319
if (opt_drop_database)
2320
fprintf(md_result_file,
2321
"\nDROP DATABASE IF EXISTS %s;\n",
2323
row = drizzle_row_next(&result);
2324
if (row != NULL && row[1])
2326
fprintf(md_result_file,"\n%s;\n",row[1]);
2329
drizzle_result_free(&result);
2333
} /* init_dumping_tables */
2336
static int init_dumping(char *database, int init_func(char*))
2338
drizzle_result_st result;
2339
drizzle_return_t ret;
2341
if (!my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
2344
if (drizzle_select_db(&dcon, &result, database, &ret) == NULL ||
2345
ret != DRIZZLE_RETURN_OK)
2347
DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
2348
return 1; /* If --force */
2350
drizzle_result_free(&result);
2352
if (!path && !opt_xml)
2354
if (opt_databases || opt_alldbs)
2357
length of table name * 2 (if name contains quotes), 2 quotes and 0
2359
char quoted_database_buf[DRIZZLE_MAX_DB_SIZE*2+3];
2360
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
2363
fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
2364
check_io(md_result_file);
2367
/* Call the view or table specific function */
2368
init_func(qdatabase);
2370
fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
2371
check_io(md_result_file);
2374
if (extended_insert)
2375
extended_row.clear();
2377
} /* init_dumping */
2380
/* Return 1 if we should copy the table */
2382
static bool include_table(const unsigned char *hash_key, size_t len)
2384
return !hash_search(&ignore_table, hash_key, len);
2388
static int dump_all_tables_in_db(char *database)
2391
char hash_key[DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2]; /* "db.tablename" */
2393
drizzle_result_st result;
2394
drizzle_return_t ret;
2396
afterdot= strcpy(hash_key, database) + strlen(database);
2399
if (init_dumping(database, init_dumping_tables))
2402
print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NULL);
2405
if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
2406
ret != DRIZZLE_RETURN_OK)
2408
DB_error(&result, ret, _("when doing refresh"));
2409
/* We shall continue here, if --force was given */
2412
drizzle_result_free(&result);
2414
while ((table= getTableName(0)))
2416
char *end= strcpy(afterdot, table) + strlen(table);
2417
if (include_table((unsigned char*) hash_key, end - hash_key))
2419
dump_table(table,database);
2426
fputs("</database>\n", md_result_file);
2427
check_io(md_result_file);
2431
} /* dump_all_tables_in_db */
2435
get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
2436
table name from the server for the table name given on the command line.
2437
we do this because the table name given on the command line may be a
2438
different case (e.g. T1 vs t1)
2441
pointer to the table name
2445
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
2448
drizzle_result_st result;
2450
char query[50 + 2*DRIZZLE_MAX_TABLE_SIZE];
2451
char show_name_buff[FN_REFLEN];
2455
/* Check memory for quote_for_like() */
2456
assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
2457
snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
2458
quote_for_like(old_table_name, show_name_buff));
2460
if (drizzleclient_query_with_error_report(&dcon, &result, query, false))
2463
num_rows= drizzle_result_row_count(&result);
2469
TODO: Return all matching rows
2471
row= drizzle_row_next(&result);
2472
lengths= drizzle_row_field_sizes(&result);
2473
name= strmake_root(root, row[0], lengths[0]);
2475
drizzle_result_free(&result);
2481
static int dump_selected_tables(char *db, char **table_names, int tables)
2484
char **dump_tables, **pos, **end;
2485
drizzle_result_st result;
2486
drizzle_return_t ret;
2489
if (init_dumping(db, init_dumping_tables))
2492
init_alloc_root(&root, 8192, 0);
2493
if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
2494
die(EX_EOM, _("alloc_root failure."));
2496
for (; tables > 0 ; tables-- , table_names++)
2498
/* the table name passed on commandline may be wrong case */
2499
if ((*pos= get_actual_table_name(*table_names, &root)))
2507
free_root(&root, MYF(0));
2509
maybe_die(EX_ILLEGAL_TABLE, _("Couldn't find table: \"%s\""), *table_names);
2510
/* We shall countinue here, if --force was given */
2517
if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
2518
ret != DRIZZLE_RETURN_OK)
2521
free_root(&root, MYF(0));
2522
DB_error(&result, ret, _("when doing refresh"));
2523
/* We shall countinue here, if --force was given */
2526
drizzle_result_free(&result);
2529
print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NULL);
2531
/* Dump each selected table */
2532
for (pos= dump_tables; pos < end; pos++)
2533
dump_table(*pos, db);
2535
free_root(&root, MYF(0));
2540
fputs("</database>\n", md_result_file);
2541
check_io(md_result_file);
414
2544
} /* dump_selected_tables */
416
static int do_flush_tables_read_lock()
2546
static int do_flush_tables_read_lock(drizzle_con_st *drizzle_con)
419
2549
We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
420
2550
will wait but will not stall the whole mysqld, and when the long update is
421
2551
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
2552
FLUSH TABLES is to lower the probability of a stage where both mysqldump
423
2553
and most client connections are stalled. Of course, if a second long
424
2554
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");
2557
( drizzleclient_query_with_error_report(drizzle_con, 0, "FLUSH TABLES", false) ||
2558
drizzleclient_query_with_error_report(drizzle_con, 0,
2559
"FLUSH TABLES WITH READ LOCK", false) );
2562
static int do_unlock_tables(drizzle_con_st *drizzle_con)
2564
return drizzleclient_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES", false);
2567
static int start_transaction(drizzle_con_st *drizzle_con)
2569
return (drizzleclient_query_with_error_report(drizzle_con, 0,
2570
"SET SESSION TRANSACTION ISOLATION "
2571
"LEVEL REPEATABLE READ", false) ||
2572
drizzleclient_query_with_error_report(drizzle_con, 0,
2573
"START TRANSACTION "
2574
"WITH CONSISTENT SNAPSHOT", false));
2578
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
2579
char **err_pos, uint32_t *err_len)
2581
const char *end= x + length;
2586
*err_pos= 0; /* No error yet */
2587
while (end > x && my_isspace(charset_info, end[-1]))
2593
const char *start= x;
2596
const char *pos= start;
2599
for (; pos != end && *pos != ','; pos++) ;
2600
var_len= (uint32_t) (pos - start);
2601
strncpy(buff, start, min((uint32_t)sizeof(buff), var_len+1));
2602
find= find_type(buff, lib, var_len);
2605
*err_pos= (char*) start;
2609
found|= (uint32_t)((int64_t) 1 << (find - 1));
2619
/* Print a value with a prefix on file */
2620
static void print_value(FILE *file, drizzle_result_st *result, drizzle_row_t row,
2621
const char *prefix, const char *name,
2624
drizzle_column_st *column;
2625
drizzle_column_seek(result, 0);
2627
for ( ; (column= drizzle_column_next(result)) ; row++)
2629
if (!strcmp(drizzle_column_name(column),name))
2631
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
2634
fputs(prefix, file);
2636
unescape(file,row[0],(uint32_t) strlen(row[0]));
2638
fputs(row[0], file);
2644
return; /* This shouldn't happen */
2648
* Fetches a row from a result based on a field name
2649
* Returns const char* of the data in that row or NULL if not found
2652
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row, const char *name)
2654
drizzle_column_st *column;
2655
drizzle_column_seek(result, 0);
2657
for ( ; (column= drizzle_column_next(result)) ; row++)
2659
if (!strcmp(drizzle_column_name(column),name))
2661
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
2663
drizzle_column_seek(result, 0);
2668
drizzle_column_seek(result, 0);
2676
Check if we the table is one of the table types that should be ignored:
2677
MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
2678
If the table should be altogether ignored, it returns a true, false if it
2679
should not be ignored. If the user has selected to use INSERT DELAYED, it
2680
sets the value of the bool pointer supports_delayed_inserts to 0 if not
2681
supported, 1 if it is supported.
2685
check_if_ignore_table()
2686
table_name Table name to check
2687
table_type Type of table
2690
drizzle Drizzle connection
2691
verbose Write warning messages
2694
char (bit value) See IGNORE_ values at top
2697
char check_if_ignore_table(const char *table_name, char *table_type)
2699
char result= IGNORE_NONE;
2700
char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
2701
const char *number_of_rows= NULL;
2702
drizzle_result_st res;
2705
/* Check memory for quote_for_like() */
2706
assert(2*sizeof(table_name) < sizeof(show_name_buff));
2707
snprintf(buff, sizeof(buff), "show table status like %s",
2708
quote_for_like(table_name, show_name_buff));
2709
if (drizzleclient_query_with_error_report(&dcon, &res, buff, false))
2713
if (!(row= drizzle_row_next(&res)))
2716
_("Error: Couldn't read status information for table %s\n"),
2718
drizzle_result_free(&res);
2719
return(result); /* assume table is ok */
2723
if ((number_of_rows= fetch_named_row(&res, row, "Rows")) != NULL)
2725
total_rows= strtoul(number_of_rows, NULL, 10);
2729
If the table type matches any of these, we do support delayed inserts.
2730
Note: we do not want to skip dumping this table if if is not one of
2731
these types, but we do want to use delayed inserts in the dump if
2732
the table type is _NOT_ one of these types
2735
strncpy(table_type, row[1], DRIZZLE_MAX_TABLE_SIZE-1);
2738
if (strcmp(table_type,"MyISAM") &&
2739
strcmp(table_type,"ARCHIVE") &&
2740
strcmp(table_type,"HEAP") &&
2741
strcmp(table_type,"MEMORY"))
2742
result= IGNORE_INSERT_DELAYED;
2745
drizzle_result_free(&res);
2751
Get string of comma-separated primary key field names
2754
char *primary_key_fields(const char *table_name)
2755
RETURNS pointer to allocated buffer (must be freed by caller)
2756
table_name quoted table name
2759
Use SHOW KEYS FROM table_name, allocate a buffer to hold the
2760
field names, and then build that string and return the pointer
2763
Returns NULL if there is no PRIMARY or UNIQUE key on the table,
2764
or if there is some failure. It is better to continue to dump
2765
the table unsorted, rather than exit without dumping the data.
2768
static char *primary_key_fields(const char *table_name)
2770
drizzle_result_st res;
2771
drizzle_return_t ret;
2773
/* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
2774
char show_keys_buff[15 + DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
2775
uint32_t result_length= 0;
2777
char buff[DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
2780
snprintf(show_keys_buff, sizeof(show_keys_buff),
2781
"SHOW KEYS FROM %s", table_name);
2782
if (drizzle_query_str(&dcon, &res, show_keys_buff, &ret) == NULL ||
2783
ret != DRIZZLE_RETURN_OK)
2785
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2787
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2788
" records are NOT sorted (%s)\n"),
2789
table_name, drizzle_result_error(&res));
2790
drizzle_result_free(&res);
2794
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2795
" records are NOT sorted (%s)\n"),
2796
table_name, drizzle_con_error(&dcon));
2802
if (drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
2804
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2805
" records are NOT sorted (%s)\n"),
2806
table_name, drizzle_con_error(&dcon));
2811
* Figure out the length of the ORDER BY clause result.
2812
* Note that SHOW KEYS is ordered: a PRIMARY key is always the first
2813
* row, and UNIQUE keys come before others. So we only need to check
2814
* the first key, not all keys.
2816
if ((row= drizzle_row_next(&res)) && atoi(row[1]) == 0)
2821
quoted_field= quote_name(row[4], buff, 0);
2822
result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
2823
} while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1);
2826
/* Build the ORDER BY clause result */
2830
/* result (terminating \0 is already in result_length) */
2831
result= (char *)malloc(result_length + 10);
2834
fprintf(stderr, _("Error: Not enough memory to store ORDER BY clause\n"));
2835
drizzle_result_free(&res);
2838
drizzle_row_seek(&res, 0);
2839
row= drizzle_row_next(&res);
2840
quoted_field= quote_name(row[4], buff, 0);
2841
end= strcpy(result, quoted_field) + strlen(quoted_field);
2842
while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1)
2844
quoted_field= quote_name(row[4], buff, 0);
2845
end+= sprintf(end,",%s",quoted_field);
2849
drizzle_result_free(&res);
446
2854
int main(int argc, char **argv)
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();
2857
MY_INIT("drizzledump");
2858
drizzle_result_st result;
2860
compatible_mode_normal_str[0]= 0;
2861
default_charset= (char *)drizzle_universal_client_charset;
2862
memset(&ignore_table, 0, sizeof(ignore_table));
2864
exit_code= get_options(&argc, &argv);
732
2867
free_resources();
733
2868
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())
2871
if (connect_to_db(current_host, current_user, opt_password))
2874
exit(EX_DRIZZLEERR);
2877
write_header(md_result_file, *argv);
2879
if ((opt_lock_all_tables) && do_flush_tables_read_lock(&dcon))
2881
if (opt_single_transaction && start_transaction(&dcon))
770
2883
if (opt_lock_all_tables)
771
db_connection->queryNoResult("FLUSH LOGS");
772
if (opt_single_transaction && do_unlock_tables()) /* unlock but no commit! */
2885
if (drizzleclient_query_with_error_report(&dcon, &result, "FLUSH LOGS", false))
2887
drizzle_result_free(&result);
2888
flush_logs= 0; /* not anymore; that would not be sensible */
2890
if (opt_single_transaction && do_unlock_tables(&dcon)) /* unlock but no commit! */
777
2895
dump_all_databases();
780
if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
2897
else if (argc > 1 && !opt_databases)
782
string database_used= *vm["database-used"].as< vector<string> >().begin();
783
2899
/* 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)
2900
dump_selected_tables(*argv, (argv + 1), (argc - 1));
2904
dump_databases(argv);
814
2907
/* ensure dumped data flushed */
815
2908
if (md_result_file && fflush(md_result_file))