73
66
/* Size of buffer for dump's select query */
74
67
#define QUERY_LENGTH 1536
68
#define DRIZZLE_MAX_LINE_LENGTH 1024*1024L-1025
76
70
/* ignore table flags */
77
71
#define IGNORE_NONE 0x00 /* no ignore */
78
72
#define IGNORE_DATA 0x01 /* don't dump data for this table */
79
73
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
81
bool opt_alltspcs= false;
82
bool opt_complete_insert= false;
84
static bool use_drizzle_protocol= false;
85
bool ignore_errors= false;
75
static void add_load_option(string &str, const char *option,
76
const char *option_value);
77
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
78
char **err_pos, uint32_t *err_len);
80
static void field_escape(string &in, const char *from);
81
static bool verbose= false;
82
static bool opt_no_create_info= false;
83
static bool opt_no_data= false;
84
static bool quick= true;
85
static bool extended_insert= true;
86
static bool ignore_errors= false;
86
87
static bool flush_logs= false;
88
static bool opt_drop= true;
89
static bool opt_keywords= false;
90
static bool opt_compress= false;
91
static bool opt_delayed= false;
87
92
static bool create_options= true;
88
93
static bool opt_quoted= false;
89
bool opt_databases= false;
90
bool opt_alldbs= false;
94
static bool opt_databases= false;
95
static bool opt_alldbs= false;
96
static bool opt_create_db= false;
91
97
static bool opt_lock_all_tables= false;
98
static bool opt_set_charset= false;
92
99
static bool opt_dump_date= true;
93
bool opt_autocommit= false;
100
static bool opt_autocommit= false;
101
static bool opt_disable_keys= true;
102
static bool opt_xml= false;
103
static bool tty_password= false;
94
104
static bool opt_single_transaction= false;
95
static bool opt_comments;
96
static bool opt_compact;
97
bool opt_ignore= false;
98
bool opt_drop_database;
99
bool opt_no_create_info;
100
bool opt_no_data= false;
101
bool opt_create_db= false;
102
bool opt_disable_keys= true;
103
bool extended_insert= true;
104
bool opt_replace_into= false;
106
uint32_t show_progress_size= 0;
105
static bool opt_comments= false;
106
static bool opt_compact= false;
107
static bool opt_hex_blob= false;
108
static bool opt_order_by_primary=false;
109
static bool opt_ignore= false;
110
static bool opt_complete_insert= false;
111
static bool opt_drop_database= false;
112
static bool opt_replace_into= false;
113
static bool opt_routines= false;
114
static bool opt_alltspcs= false;
115
static bool debug_info_flag= false;
116
static bool debug_check_flag= false;
117
static uint32_t show_progress_size= 0;
118
static uint64_t total_rows= 0;
119
static drizzle_st drizzle;
120
static drizzle_con_st dcon;
107
121
static string insert_pat;
122
static char *opt_password= NULL;
123
static char *current_user= NULL;
124
static char *current_host= NULL;
125
static char *path= NULL;
126
static char *fields_terminated= NULL;
127
static char *lines_terminated= NULL;
128
static char *enclosed= NULL;
129
static char *opt_enclosed= NULL;
130
static char *escaped= NULL;
131
static char *where= NULL;
132
static char *order_by= NULL;
133
static char *opt_compatible_mode_str= NULL;
134
static char *err_ptr= NULL;
135
static char **defaults_argv= NULL;
136
static char compatible_mode_normal_str[255];
137
static uint32_t opt_compatible_mode= 0;
108
138
static uint32_t opt_drizzle_port= 0;
139
static uint32_t my_end_arg;
109
140
static int first_error= 0;
110
141
static string extended_row;
111
142
FILE *md_result_file= 0;
112
143
FILE *stderror_file= 0;
113
std::vector<DrizzleDumpDatabase*> database_store;
114
DrizzleDumpConnection* db_connection;
115
DrizzleDumpConnection* destination_connection;
123
int opt_destination= DESTINATION_STDOUT;
124
std::string opt_destination_host;
125
uint16_t opt_destination_port;
126
std::string opt_destination_user;
127
std::string opt_destination_password;
128
std::string opt_destination_database;
130
const string progname= "drizzledump";
142
//static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
144
boost::unordered_set<string> ignore_table;
146
void maybe_exit(int error);
145
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
147
static const char *compatible_mode_names[]=
149
"MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
150
"MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
154
static TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
155
"", compatible_mode_names, NULL};
157
drizzled::hash_set<string> ignore_table;
159
static struct my_option my_long_options[] =
161
{"all", 'a', "Deprecated. Use --create-options instead.",
162
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
164
{"all-databases", 'A',
165
"Dump all the databases. This will be same as --databases with all databases selected.",
166
(char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
168
{"all-tablespaces", 'Y',
169
"Dump all the tablespaces.",
170
(char**) &opt_alltspcs, (char**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
172
{"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
173
(char**) &opt_drop_database, (char**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
175
{"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
176
(char**) &opt_drop, (char**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
178
{"allow-keywords", OPT_KEYWORDS,
179
"Allow creation of column names that are keywords.", (char**) &opt_keywords,
180
(char**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
181
{"comments", 'i', "Write additional information.",
182
(char**) &opt_comments, (char**) &opt_comments, 0, GET_BOOL, NO_ARG,
184
{"compatible", OPT_COMPATIBLE,
185
"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.",
186
(char**) &opt_compatible_mode_str, (char**) &opt_compatible_mode_str, 0,
187
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
188
{"compact", OPT_COMPACT,
189
"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",
190
(char**) &opt_compact, (char**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
192
{"complete-insert", 'c', "Use complete insert statements.",
193
(char**) &opt_complete_insert, (char**) &opt_complete_insert, 0, GET_BOOL,
194
NO_ARG, 0, 0, 0, 0, 0, 0},
195
{"compress", 'C', "Use compression in server/client protocol.",
196
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
198
{"create-options", OPT_CREATE_OPTIONS,
199
"Include all DRIZZLE specific create options.",
200
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
203
"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.",
204
(char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
206
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
207
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
208
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
209
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
210
(char**) &debug_info_flag, (char**) &debug_info_flag,
211
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
212
{"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
213
(char**) &opt_delayed, (char**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
215
{"disable-keys", 'K',
216
"'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will be put in the output.", (char**) &opt_disable_keys,
217
(char**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
218
{"extended-insert", 'e',
219
"Allows utilization of the new, much faster INSERT syntax.",
220
(char**) &extended_insert, (char**) &extended_insert, 0, GET_BOOL, NO_ARG,
222
{"fields-terminated-by", OPT_FTB,
223
"Fields in the textfile are terminated by ...", (char**) &fields_terminated,
224
(char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
225
{"fields-enclosed-by", OPT_ENC,
226
"Fields in the importfile are enclosed by ...", (char**) &enclosed,
227
(char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
228
{"fields-optionally-enclosed-by", OPT_O_ENC,
229
"Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
230
(char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
231
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
232
(char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
233
{"flush-logs", 'F', "Flush logs file in server before starting dump. "
234
"Note that if you dump many databases at once (using the option "
235
"--databases= or --all-databases), the logs will be flushed for "
236
"each database dumped. The exception is when using --lock-all-tables "
237
"in this case the logs will be flushed only once, corresponding "
238
"to the moment all tables are locked. So if you want your dump and "
239
"the log flush to happen at the same exact moment you should use "
240
"--lock-all-tables or --flush-logs",
241
(char**) &flush_logs, (char**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
243
{"force", 'f', "Continue even if we get an sql-error.",
244
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG,
246
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
247
NO_ARG, 0, 0, 0, 0, 0, 0},
248
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
249
"VARBINARY, BLOB) in hexadecimal format.",
250
(char**) &opt_hex_blob, (char**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
251
{"host", 'h', "Connect to host.", (char**) ¤t_host,
252
(char**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
253
{"ignore-table", OPT_IGNORE_TABLE,
254
"Do not dump the specified table. To specify more than one table to ignore, "
255
"use the directive multiple times, once for each table. Each table must "
256
"be specified with both database and table names, e.g. --ignore-table=database.table",
257
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
258
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
259
(char**) &opt_ignore, (char**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
261
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
262
(char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
263
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
264
{"lock-all-tables", 'x', "Locks all tables across all databases. This "
265
"is achieved by taking a global read lock for the duration of the whole "
266
"dump. Automatically turns --single-transaction and --lock-tables off.",
267
(char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
269
{"no-autocommit", OPT_AUTOCOMMIT,
270
"Wrap tables with autocommit/commit statements.",
271
(char**) &opt_autocommit, (char**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
273
{"no-create-db", 'n',
274
"'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.}.",
275
(char**) &opt_create_db, (char**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
277
{"no-create-info", 't', "Don't write table creation info.",
278
(char**) &opt_no_create_info, (char**) &opt_no_create_info, 0, GET_BOOL,
279
NO_ARG, 0, 0, 0, 0, 0, 0},
280
{"no-data", 'd', "No row information.", (char**) &opt_no_data,
281
(char**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
282
{"no-set-names", 'N',
283
"Deprecated. Use --skip-set-charset instead.",
284
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
285
{"opt", OPT_OPTIMIZE,
286
"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.",
287
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
288
{"order-by-primary", OPT_ORDER_BY_PRIMARY,
289
"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.",
290
(char**) &opt_order_by_primary, (char**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
292
"Password to use when connecting to server. If password is not given it's solicited on the tty.",
293
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
294
{"port", 'p', "Port number to use for connection.",
295
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
296
{"quick", 'q', "Don't buffer query, dump directly to stdout.",
297
(char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
298
{"quote-names",'Q', "Quote table and column names with backticks (`).",
299
(char**) &opt_quoted, (char**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
301
{"replace", OPT_DRIZZLE_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
302
(char**) &opt_replace_into, (char**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
305
"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).",
306
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
307
{"routines", 'R', "Dump stored routines (functions and procedures).",
308
(char**) &opt_routines, (char**) &opt_routines, 0, GET_BOOL,
309
NO_ARG, 0, 0, 0, 0, 0, 0},
310
{"single-transaction", OPT_TRANSACTION,
311
"Creates a consistent snapshot by dumping all tables in a single "
312
"transaction. Works ONLY for tables stored in storage engines which "
313
"support multiversioning (currently only InnoDB does); the dump is NOT "
314
"guaranteed to be consistent for other storage engines. "
315
"While a --single-transaction dump is in process, to ensure a valid "
316
"dump file (correct table contents), no other "
317
"connection should use the following statements: ALTER TABLE, DROP "
318
"TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
319
"isolated from them. Option automatically turns off --lock-tables.",
320
(char**) &opt_single_transaction, (char**) &opt_single_transaction, 0,
321
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
322
{"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
323
(char**) &opt_dump_date, (char**) &opt_dump_date, 0,
324
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
325
{"skip-opt", OPT_SKIP_OPTIMIZATION,
326
"Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
327
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
329
"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.",
330
(char**) &path, (char**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
331
{"tables", OPT_TABLES, "Overrides option --databases (-B).",
332
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
333
{"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of rows before each output progress report (requires --verbose)."),
334
(char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
335
10000, 0, 0, 0, 0, 0},
336
{"user", 'u', "User for login if not current user.",
337
(char**) ¤t_user, (char**) ¤t_user, 0, GET_STR, REQUIRED_ARG,
339
{"verbose", 'v', "Print info about the various stages.",
340
(char**) &verbose, (char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
341
{"version",'V', "Output version information and exit.", 0, 0, 0,
342
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
343
{"where", 'w', "Dump only selected records; QUOTES mandatory!",
344
(char**) &where, (char**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
345
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
346
NO_ARG, 0, 0, 0, 0, 0, 0},
347
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
350
static const char *load_default_groups[]= { "drizzledump","client",0 };
352
static void maybe_exit(int error);
147
353
static void die(int error, const char* reason, ...);
148
static void write_header(char *db_name);
149
static int dump_selected_tables(const string &db, const vector<string> &table_names);
150
static int dump_databases(const vector<string> &db_names);
354
static void maybe_die(int error, const char* reason, ...);
355
static void write_header(FILE *sql_file, char *db_name);
356
static void print_value(FILE *file, drizzle_result_st *result,
357
drizzle_row_t row, const char *prefix, const char *name,
359
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row,
361
static int dump_selected_tables(char *db, char **table_names, int tables);
362
static int dump_all_tables_in_db(char *db);
363
static int init_dumping_tables(char *);
364
static int init_dumping(char *, int init_func(char*));
365
static int dump_databases(char **);
151
366
static int dump_all_databases(void);
152
int get_server_type();
153
void dump_all_tables(void);
154
void generate_dump(void);
155
void generate_dump_db(void);
157
void dump_all_tables(void)
159
std::vector<DrizzleDumpDatabase*>::iterator i;
160
for (i= database_store.begin(); i != database_store.end(); ++i)
162
if ((not (*i)->populateTables()) && (not ignore_errors))
163
maybe_exit(EX_DRIZZLEERR);
167
void generate_dump(void)
169
std::vector<DrizzleDumpDatabase*>::iterator i;
173
cout << endl << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;"
174
<< endl << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
178
cout << "SET AUTOCOMMIT=0;" << endl;
180
for (i= database_store.begin(); i != database_store.end(); ++i)
182
DrizzleDumpDatabase *database= *i;
188
cout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;"
189
<< endl << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
193
void generate_dump_db(void)
195
std::vector<DrizzleDumpDatabase*>::iterator i;
196
DrizzleStringBuf sbuf(1024);
199
destination_connection= new DrizzleDumpConnection(opt_destination_host,
200
opt_destination_port, opt_destination_user, opt_destination_password,
203
catch (std::exception&)
205
cerr << "Could not connect to destination database server" << endl;
206
maybe_exit(EX_DRIZZLEERR);
208
sbuf.setConnection(destination_connection);
209
std::ostream sout(&sbuf);
210
sout.exceptions(ios_base::badbit);
214
sout << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;" << endl;
215
sout << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
219
cout << "SET AUTOCOMMIT=0;" << endl;
221
for (i= database_store.begin(); i != database_store.end(); ++i)
225
DrizzleDumpDatabase *database= *i;
228
catch (std::exception&)
230
std::cout << _("Error inserting into destination database") << std::endl;
231
if (not ignore_errors)
232
maybe_exit(EX_DRIZZLEERR);
238
sout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;" << endl;
239
sout << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
367
static char *quote_name(const char *name, char *buff, bool force);
368
char check_if_ignore_table(const char *table_name, char *table_type);
369
static char *primary_key_fields(const char *table_name);
372
Print the supplied message if in verbose mode
377
... variable number of parameters
379
static void verbose_msg(const char *fmt, ...)
388
vfprintf(stderr, fmt, args);
244
393
exit with message if ferror(file)
251
400
static void check_io(FILE *file)
335
770
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
338
fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
773
fprintf(stderr, "%s: %s\n", my_progname, buffer);
341
776
ignore_errors= 0; /* force the exit */
342
777
maybe_exit(error_num);
782
Prints out an error message and maybe kills the process.
786
error_num - process return value
787
fmt_reason - a format string for use by vsnprintf.
788
... - variable arguments for above fmt_reason string
791
This call prints out the formatted error message to stderr and then
792
terminates the process, unless the --force command line option is used.
794
This call should be used for non-fatal errors (such as database
795
errors) that the code may still be able to continue to the next unit
799
static void maybe_die(int error_num, const char* fmt_reason, ...)
803
va_start(args,fmt_reason);
804
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
807
fprintf(stderr, "%s: %s\n", my_progname, buffer);
810
maybe_exit(error_num);
816
Sends a query to server, optionally reads result, prints error message if
820
drizzleclient_query_with_error_report()
821
drizzle_con connection to use
822
res if non zero, result will be put there with
823
drizzleclient_store_result()
824
query query to send to server
827
0 query sending and (if res!=0) result reading went ok
831
static int drizzleclient_query_with_error_report(drizzle_con_st *con,
832
drizzle_result_st *result,
833
const char *query_str,
836
drizzle_return_t ret;
838
if (drizzle_query_str(con, result, query_str, &ret) == NULL ||
839
ret != DRIZZLE_RETURN_OK)
841
if (ret == DRIZZLE_RETURN_ERROR_CODE)
843
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
844
query_str, drizzle_result_error(result),
845
drizzle_result_error_code(result));
846
drizzle_result_free(result);
850
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
851
query_str, drizzle_con_error(con), ret);
857
ret= drizzle_column_buffer(result);
859
ret= drizzle_result_buffer(result);
860
if (ret != DRIZZLE_RETURN_OK)
862
drizzle_result_free(result);
863
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
864
query_str, drizzle_con_error(con), ret);
872
Open a new .sql file to dump the table or view into
875
open_sql_file_for_table
876
name name of the table or view
879
0 Failed to open file
880
> 0 Handle of the open file
882
static FILE* open_sql_file_for_table(const char* table)
885
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
886
convert_dirname(tmp_path,path,NULL);
887
res= fopen(fn_format(filename, table, tmp_path, ".sql", 4), "w");
345
893
static void free_resources(void)
347
895
if (md_result_file && md_result_file != stdout)
348
896
fclose(md_result_file);
349
opt_password.erase();
899
free_defaults(defaults_argv);
353
void maybe_exit(int error)
904
static void maybe_exit(int error)
355
906
if (!first_error)
356
907
first_error= error;
357
908
if (ignore_errors)
359
delete db_connection;
360
delete destination_connection;
910
drizzle_con_free(&dcon);
911
drizzle_free(&drizzle);
361
912
free_resources();
918
db_connect -- connects to the host and selects DB.
921
static int connect_to_db(char *host, char *user,char *passwd)
923
drizzle_return_t ret;
925
verbose_msg(_("-- Connecting to %s...\n"), host ? host : "localhost");
926
drizzle_create(&drizzle);
927
drizzle_con_create(&drizzle, &dcon);
928
drizzle_con_set_tcp(&dcon, host, opt_drizzle_port);
929
drizzle_con_set_auth(&dcon, user, passwd);
930
ret= drizzle_con_connect(&dcon);
931
if (ret != DRIZZLE_RETURN_OK)
933
DB_error(NULL, ret, "when trying to connect");
938
} /* connect_to_db */
942
** dbDisconnect -- disconnects from the host.
944
static void dbDisconnect(char *host)
946
verbose_msg(_("-- Disconnecting from %s...\n"), host ? host : "localhost");
947
drizzle_con_free(&dcon);
948
drizzle_free(&drizzle);
952
static void unescape(FILE *file,char *pos,uint32_t length)
956
if (!(tmp=(char*) malloc(length*2+1)))
957
die(EX_DRIZZLEERR, _("Couldn't allocate memory"));
959
drizzle_escape_string(tmp, pos, length);
969
static bool test_if_special_chars(const char *str)
971
for ( ; *str ; str++)
972
if (!my_isvar(charset_info,*str) && *str != '$')
975
} /* test_if_special_chars */
980
quote_name(name, buff, force)
982
Quotes char string, taking into account compatible mode
986
name Unquoted string containing that which will be quoted
987
buff The buffer that contains the quoted value, also returned
988
force Flag to make it ignore 'test_if_special_chars'
995
static char *quote_name(const char *name, char *buff, bool force)
1000
if (!force && !opt_quoted && !test_if_special_chars(name))
1001
return (char*) name;
1016
Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
1020
name name of the table
1021
buff quoted name of the table
1024
Quote \, _, ' and % characters
1026
Note: Because DRIZZLE uses the C escape syntax in strings
1027
(for example, '\n' to represent newline), you must double
1028
any '\' that you use in your LIKE strings. For example, to
1029
search for '\n', specify it as '\\n'. To search for '\', specify
1030
it as '\\\\' (the backslashes are stripped once by the parser
1031
and another time when the pattern match is done, leaving a
1032
single backslash to be matched).
1034
Example: "t\1" => "t\\\\1"
1037
static char *quote_for_like(const char *name, char *buff)
1049
else if (*name == '\'' || *name == '_' || *name == '%')
1060
Quote and print a string.
1064
xml_file - output file
1065
str - string to print
1069
Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1072
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
1076
for (end= str + len; str != end; str++)
1080
fputs("<", xml_file);
1083
fputs(">", xml_file);
1086
fputs("&", xml_file);
1089
fputs(""", xml_file);
1092
fputc(*str, xml_file);
1101
Print xml tag. Optionally add attribute(s).
1104
print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
1105
..., attribute_name_n, attribute_value_n, NULL)
1106
xml_file - output file
1107
sbeg - line beginning
1108
line_end - line ending
1109
tag_name - XML tag name.
1110
first_attribute_name - tag and first attribute
1111
first_attribute_value - (Implied) value of first attribute
1112
attribute_name_n - attribute n
1113
attribute_value_n - value of attribute n
1116
Print XML tag with any number of attribute="value" pairs to the xml_file.
1119
sbeg<tag_name first_attribute_name="first_attribute_value" ...
1120
attribute_name_n="attribute_value_n">send
1122
Additional arguments must be present in attribute/value pairs.
1123
The last argument should be the null character pointer.
1124
All attribute_value arguments MUST be NULL terminated strings.
1125
All attribute_value arguments will be quoted before output.
1128
static void print_xml_tag(FILE * xml_file, const char* sbeg,
1129
const char* line_end,
1130
const char* tag_name,
1131
const char* first_attribute_name, ...)
1134
const char *attribute_name, *attribute_value;
1136
fputs(sbeg, xml_file);
1137
fputc('<', xml_file);
1138
fputs(tag_name, xml_file);
1140
va_start(arg_list, first_attribute_name);
1141
attribute_name= first_attribute_name;
1142
while (attribute_name != NULL)
1144
attribute_value= va_arg(arg_list, char *);
1145
assert(attribute_value != NULL);
1147
fputc(' ', xml_file);
1148
fputs(attribute_name, xml_file);
1149
fputc('\"', xml_file);
1151
print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
1152
fputc('\"', xml_file);
1154
attribute_name= va_arg(arg_list, char *);
1158
fputc('>', xml_file);
1159
fputs(line_end, xml_file);
1165
Print xml tag with for a field that is null
1168
print_xml_null_tag()
1169
xml_file - output file
1170
sbeg - line beginning
1171
stag_atr - tag and attribute
1172
sval - value of attribute
1173
line_end - line ending
1176
Print tag with one attribute to the xml_file. Format is:
1177
<stag_atr="sval" xsi:nil="true"/>
1179
sval MUST be a NULL terminated string.
1180
sval string will be qouted before output.
1183
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
1184
const char* stag_atr, const char* sval,
1185
const char* line_end)
1187
fputs(sbeg, xml_file);
1188
fputs("<", xml_file);
1189
fputs(stag_atr, xml_file);
1190
fputs("\"", xml_file);
1191
print_quoted_xml(xml_file, sval, strlen(sval));
1192
fputs("\" xsi:nil=\"true\" />", xml_file);
1193
fputs(line_end, xml_file);
1199
Print xml tag with many attributes.
1203
xml_file - output file
1204
row_name - xml tag name
1205
tableRes - query result
1209
Print tag with many attribute to the xml_file. Format is:
1210
\t\t<row_name Atr1="Val1" Atr2="Val2"... />
1212
All atributes and values will be quoted before output.
1215
static void print_xml_row(FILE *xml_file, const char *row_name,
1216
drizzle_result_st *tableRes, drizzle_row_t *row)
1219
drizzle_column_st *column;
1220
size_t *lengths= drizzle_row_field_sizes(tableRes);
1222
fprintf(xml_file, "\t\t<%s", row_name);
1224
drizzle_column_seek(tableRes, 0);
1225
for (i= 0; (column= drizzle_column_next(tableRes)); i++)
1229
fputc(' ', xml_file);
1230
print_quoted_xml(xml_file, drizzle_column_name(column),
1231
strlen(drizzle_column_name(column)));
1232
fputs("=\"", xml_file);
1233
print_quoted_xml(xml_file, (*row)[i], lengths[i]);
1234
fputc('"', xml_file);
1238
fputs(" />\n", xml_file);
1244
Print hex value for blob data.
1248
output_file - output file
1249
str - string to print
1253
Print hex value for blob data.
1256
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
1258
/* sakaik got the idea to to provide blob's in hex notation. */
1259
const char *ptr= str, *end= ptr + len;
1260
for (; ptr < end ; ptr++)
1261
fprintf(output_file, "%02X", *((unsigned char *)ptr));
1262
check_io(output_file);
1266
get_table_structure -- retrievs database structure, prints out corresponding
1267
CREATE statement and fills out insert_pat if the table is the type we will
1273
table_type - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
1274
ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1275
num_fields - number of fields in the table
1278
true if success, false if error
1281
static bool get_table_structure(char *table, char *db, char *table_type,
1282
char *ignore_flag, uint64_t *num_fields)
1284
bool init=0, delayed, write_data, complete_insert;
1285
char *result_table, *opt_quoted_table;
1286
const char *insert_option;
1287
char name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE+3];
1288
char table_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+3];
1289
char table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3];
1290
char query_buff[QUERY_LENGTH];
1291
FILE *sql_file= md_result_file;
1292
drizzle_result_st result;
1295
*ignore_flag= check_if_ignore_table(table, table_type);
1297
delayed= opt_delayed;
1298
if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
1301
verbose_msg(_("-- Warning: Unable to use delayed inserts for table '%s' "
1302
"because it's of type %s\n"), table, table_type);
1306
if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1308
complete_insert= opt_complete_insert;
1312
insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
1313
delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
1315
verbose_msg(_("-- Retrieving table structure for table %s...\n"), table);
1317
result_table= quote_name(table, table_buff, 1);
1318
opt_quoted_table= quote_name(table, table_buff2, 0);
1320
if (opt_order_by_primary)
1323
order_by= primary_key_fields(result_table);
1328
/* using SHOW CREATE statement */
1329
if (!opt_no_create_info)
1331
/* Make an sql-file, if path was given iow. option -T was given */
1332
char buff[20+FN_REFLEN];
1333
const drizzle_column_st *column;
1335
snprintf(buff, sizeof(buff), "show create table %s", result_table);
1337
if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1342
if (!(sql_file= open_sql_file_for_table(table)))
1344
drizzle_result_free(&result);
1348
write_header(sql_file, db);
1350
if (!opt_xml && opt_comments)
1352
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1359
Even if the "table" is a view, we do a DROP TABLE here.
1361
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
1365
column= drizzle_column_index(&result, 0);
1367
row= drizzle_row_next(&result);
1369
fprintf(sql_file, "%s;\n", row[1]);
1372
drizzle_result_free(&result);
1375
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1378
if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
1386
If write_data is true, then we build up insert statements for
1387
the table's data. Note: in subsequent lines of code, this test
1388
will have to be performed each time we are appending to
1393
if (opt_replace_into)
1394
insert_pat.append("REPLACE ");
1396
insert_pat.append("INSERT ");
1397
insert_pat.append(insert_option);
1398
insert_pat.append("INTO ");
1399
insert_pat.append(opt_quoted_table);
1400
if (complete_insert)
1402
insert_pat.append(" (");
1406
insert_pat.append(" VALUES ");
1407
if (!extended_insert)
1408
insert_pat.append("(");
1412
while ((row= drizzle_row_next(&result)))
1414
if (complete_insert)
1418
insert_pat.append(", ");
1421
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1424
*num_fields= drizzle_result_row_count(&result);
1425
drizzle_result_free(&result);
1429
verbose_msg(_("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n"),
1430
my_progname, drizzle_con_error(&dcon));
1432
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1434
if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
1437
/* Make an sql-file, if path was given iow. option -T was given */
1438
if (!opt_no_create_info)
1442
if (!(sql_file= open_sql_file_for_table(table)))
1444
drizzle_result_free(&result);
1447
write_header(sql_file, db);
1449
if (!opt_xml && opt_comments)
1450
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1453
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1455
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
1457
print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
1464
if (opt_replace_into)
1465
insert_pat.append("REPLACE ");
1467
insert_pat.append("INSERT ");
1468
insert_pat.append(insert_option);
1469
insert_pat.append("INTO ");
1470
insert_pat.append(result_table);
1471
if (complete_insert)
1472
insert_pat.append(" (");
1475
insert_pat.append(" VALUES ");
1476
if (!extended_insert)
1477
insert_pat.append("(");
1481
while ((row= drizzle_row_next(&result)))
1483
size_t *lengths= drizzle_row_field_sizes(&result);
1486
if (!opt_xml && !opt_no_create_info)
1488
fputs(",\n",sql_file);
1491
if (complete_insert)
1492
insert_pat.append(", ");
1495
if (complete_insert)
1496
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1497
if (!opt_no_create_info)
1501
print_xml_row(sql_file, "field", &result, &row);
1506
fprintf(sql_file, " %s.%s %s", result_table,
1507
quote_name(row[SHOW_FIELDNAME],name_buff, 0),
1510
fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
1513
if (row[SHOW_DEFAULT])
1515
fputs(" DEFAULT ", sql_file);
1516
unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1518
if (!row[SHOW_NULL][0])
1519
fputs(" NOT NULL", sql_file);
1520
if (row[SHOW_EXTRA][0])
1521
fprintf(sql_file, " %s",row[SHOW_EXTRA]);
1525
*num_fields= drizzle_result_row_count(&result);
1526
drizzle_result_free(&result);
1528
if (!opt_no_create_info)
1530
/* Make an sql-file, if path was given iow. option -T was given */
1531
char buff[20+FN_REFLEN];
1532
uint32_t keynr,primary_key;
1533
snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1534
if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1536
fprintf(stderr, _("%s: Can't get keys for table %s\n"),
1537
my_progname, result_table);
1543
/* Find first which key is primary key */
1545
primary_key=INT_MAX;
1546
while ((row= drizzle_row_next(&result)))
1548
if (atoi(row[3]) == 1)
1551
#ifdef FORCE_PRIMARY_KEY
1552
if (atoi(row[1]) == 0 && primary_key == INT_MAX)
1555
if (!strcmp(row[2],"PRIMARY"))
1562
drizzle_row_seek(&result,0);
1564
while ((row= drizzle_row_next(&result)))
1568
print_xml_row(sql_file, "key", &result, &row);
1572
if (atoi(row[3]) == 1)
1575
putc(')', sql_file);
1576
if (atoi(row[1])) /* Test if duplicate key */
1577
/* Duplicate allowed */
1578
fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0));
1579
else if (keynr == primary_key)
1580
fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
1582
fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
1586
putc(',', sql_file);
1587
fputs(quote_name(row[4], name_buff, 0), sql_file);
1589
fprintf(sql_file, " (%s)",row[7]); /* Sub key */
1592
drizzle_result_free(&result);
1596
putc(')', sql_file);
1597
fputs("\n)",sql_file);
1600
/* Get DRIZZLE specific create options */
1603
char show_name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+2+24];
1605
/* Check memory for quote_for_like() */
1606
snprintf(buff, sizeof(buff), "show table status like %s",
1607
quote_for_like(table, show_name_buff));
1609
if (!drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1611
if (!(row= drizzle_row_next(&result)))
1614
_("Error: Couldn't read status information for table %s\n"),
1620
print_xml_row(sql_file, "options", &result, &row);
1623
fputs("/*!",sql_file);
1624
print_value(sql_file,&result,row,"engine=","Engine",0);
1625
print_value(sql_file,&result,row,"","Create_options",0);
1626
print_value(sql_file,&result,row,"comment=","Comment",1);
1628
fputs(" */",sql_file);
1632
drizzle_result_free(&result);
1636
fputs(";\n", sql_file);
1638
fputs("\t</table_structure>\n", sql_file);
1642
if (complete_insert) {
1643
insert_pat.append(") VALUES ");
1644
if (!extended_insert)
1645
insert_pat.append("(");
1647
if (sql_file != md_result_file)
1649
fputs("\n", sql_file);
1650
write_footer(sql_file);
1654
} /* get_table_structure */
1656
static void add_load_option(string &str, const char *option,
1657
const char *option_value)
1661
/* Null value means we don't add this option. */
1667
if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
1669
/* It's a hex constant, don't escape */
1670
str.append(option_value);
1674
/* char constant; escape */
1675
field_escape(str, option_value);
1681
Allow the user to specify field terminator strings like:
1682
"'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
1683
This is done by doubling ' and add a end -\ if needed to avoid
1684
syntax errors from the SQL parser.
1687
static void field_escape(string &in, const char *from)
1689
uint32_t end_backslashes= 0;
1698
end_backslashes^=1; /* find odd number of backslashes */
1701
if (*from == '\'' && !end_backslashes)
1703
/* We want a duplicate of "'" for DRIZZLE */
1710
/* Add missing backslashes if user has specified odd number of backs.*/
1711
if (end_backslashes)
1724
dump_table saves database contents as a series of INSERT statements.
1735
static void dump_table(char *table, char *db)
1738
char table_buff[DRIZZLE_MAX_TABLE_SIZE+3];
1739
string query_string;
1740
char table_type[DRIZZLE_MAX_TABLE_SIZE];
1741
char *result_table, table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3], *opt_quoted_table;
1743
uint32_t rownr, row_break, total_length, init_length;
1744
uint64_t num_fields= 0;
1745
drizzle_return_t ret;
1746
drizzle_result_st result;
1747
drizzle_column_st *column;
1752
Make sure you get the create table info before the following check for
1753
--no-data flag below. Otherwise, the create table info won't be printed.
1755
if (!get_table_structure(table, db, table_type, &ignore_flag, &num_fields))
1757
maybe_die(EX_TABLE_STATUS, _("Error retrieving table structure for table: \"%s\""), table);
1761
/* Check --no-data flag */
1764
verbose_msg(_("-- Skipping dump data for table '%s', --no-data was used\n"),
1770
If the table type is a merge table or any type that has to be
1771
_completely_ ignored and no data dumped
1773
if (ignore_flag & IGNORE_DATA)
1775
verbose_msg(_("-- Warning: Skipping data for table '%s' because " \
1776
"it's of type %s\n"), table, table_type);
1779
/* Check that there are any fields in the table */
1780
if (num_fields == 0)
1782
verbose_msg(_("-- Skipping dump data for table '%s', it has no fields\n"),
1787
result_table= quote_name(table,table_buff, 1);
1788
opt_quoted_table= quote_name(table, table_buff2, 0);
1790
verbose_msg(_("-- Sending SELECT query...\n"));
1792
query_string.clear();
1793
query_string.reserve(1024);
1797
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
1800
Convert the path to native os format
1801
and resolve to the full filepath.
1803
convert_dirname(tmp_path,path,NULL);
1804
my_load_path(tmp_path, tmp_path, NULL);
1805
fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
1807
/* Must delete the file that 'INTO OUTFILE' will write to */
1808
my_delete(filename, MYF(0));
1810
/* now build the query string */
1812
query_string.append( "SELECT * INTO OUTFILE '");
1813
query_string.append( filename);
1814
query_string.append( "'");
1816
if (fields_terminated || enclosed || opt_enclosed || escaped)
1817
query_string.append( " FIELDS");
1819
add_load_option(query_string, " TERMINATED BY ", fields_terminated);
1820
add_load_option(query_string, " ENCLOSED BY ", enclosed);
1821
add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
1822
add_load_option(query_string, " ESCAPED BY ", escaped);
1823
add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
1825
query_string.append( " FROM ");
1826
query_string.append( result_table);
1830
query_string.append( " WHERE ");
1831
query_string.append( where);
1836
query_string.append( " ORDER BY ");
1837
query_string.append( order_by);
1840
if (drizzle_query(&dcon, &result, query_string.c_str(),
1841
query_string.length(), &ret) == NULL ||
1842
ret != DRIZZLE_RETURN_OK)
1844
DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
1848
drizzle_result_free(&result);
1852
if (!opt_xml && opt_comments)
1854
fprintf(md_result_file,_("\n--\n-- Dumping data for table %s\n--\n"),
1856
check_io(md_result_file);
1859
query_string.append( "SELECT * FROM ");
1860
query_string.append( result_table);
1864
if (!opt_xml && opt_comments)
1866
fprintf(md_result_file, "-- WHERE: %s\n", where);
1867
check_io(md_result_file);
1870
query_string.append( " WHERE ");
1871
query_string.append( where);
1875
if (!opt_xml && opt_comments)
1877
fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
1878
check_io(md_result_file);
1880
query_string.append( " ORDER BY ");
1881
query_string.append( order_by);
1884
if (!opt_xml && !opt_compact)
1886
fputs("\n", md_result_file);
1887
check_io(md_result_file);
1889
if (drizzleclient_query_with_error_report(&dcon, &result,
1890
query_string.c_str(), quick))
1895
verbose_msg(_("-- Retrieving rows...\n"));
1896
if (drizzle_result_column_count(&result) != num_fields)
1898
fprintf(stderr,_("%s: Error in field count for table: %s ! Aborting.\n"),
1899
my_progname, result_table);
1900
error= EX_CONSCHECK;
1901
drizzle_result_free(&result);
1905
/* Moved disable keys to after lock per bug 15977 */
1906
if (opt_disable_keys)
1908
fprintf(md_result_file, "ALTER TABLE %s DISABLE KEYS;\n",
1910
check_io(md_result_file);
1913
total_length= DRIZZLE_MAX_LINE_LENGTH; /* Force row break */
1916
init_length=(uint32_t) insert_pat.length()+4;
1918
print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
1922
fprintf(md_result_file, "set autocommit=0;\n");
1923
check_io(md_result_file);
1936
drizzle_row_free(&result, row);
1938
row= drizzle_row_buffer(&result, &ret);
1939
if (ret != DRIZZLE_RETURN_OK)
1942
_("%s: Error reading rows for table: %s (%d:%s) ! Aborting.\n"),
1943
my_progname, result_table, ret, drizzle_con_error(&dcon));
1944
drizzle_result_free(&result);
1949
row= drizzle_row_next(&result);
1954
lengths= drizzle_row_field_sizes(&result);
1957
if ((rownr % show_progress_size) == 0)
1959
verbose_msg(_("-- %"PRIu32" of ~%"PRIu64" rows dumped for table %s\n"), rownr, total_rows, opt_quoted_table);
1961
if (!extended_insert && !opt_xml)
1963
fputs(insert_pat.c_str(),md_result_file);
1964
check_io(md_result_file);
1966
drizzle_column_seek(&result,0);
1970
fputs("\t<row>\n", md_result_file);
1971
check_io(md_result_file);
1974
for (i= 0; i < drizzle_result_column_count(&result); i++)
1977
uint32_t length= lengths[i];
1979
if (!(column= drizzle_column_next(&result)))
1981
_("Not enough fields from table %s! Aborting.\n"),
1985
63 is my_charset_bin. If charsetnr is not 63,
1986
we have not a BLOB but a TEXT column.
1987
we'll dump in hex only BLOB columns.
1989
is_blob= (opt_hex_blob && drizzle_column_charset(column) == 63 &&
1990
(drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_VARCHAR ||
1991
drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_BLOB)) ? 1 : 0;
1992
if (extended_insert && !opt_xml)
1996
extended_row.clear();
1997
extended_row.append("(");
2000
extended_row.append(",");
2006
if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
2009
"length * 2 + 2" is OK for both HEX and non-HEX modes:
2010
- In HEX mode we need exactly 2 bytes per character
2011
plus 2 bytes for '0x' prefix.
2012
- In non-HEX mode we need up to 2 bytes per character,
2013
plus 2 bytes for leading and trailing '\'' characters.
2014
Also we need to reserve 1 byte for terminating '\0'.
2016
char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
2017
memset(tmp_str, '\0', length * 2 + 2 + 1);
2018
if (opt_hex_blob && is_blob)
2020
extended_row.append("0x");
2021
drizzle_hex_string(tmp_str, row[i], length);
2022
extended_row.append(tmp_str);
2026
extended_row.append("'");
2027
drizzle_escape_string(tmp_str, row[i],length);
2028
extended_row.append(tmp_str);
2029
extended_row.append("'");
2035
/* change any strings ("inf", "-inf", "nan") into NULL */
2037
if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
2038
my_isalpha(charset_info, ptr[1])))
2039
extended_row.append( "NULL");
2042
extended_row.append( ptr);
2047
extended_row.append("''");
2050
extended_row.append("NULL");
2056
fputc(',', md_result_file);
2057
check_io(md_result_file);
2061
if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
2065
if (opt_hex_blob && is_blob && length)
2067
/* Define xsi:type="xs:hexBinary" for hex encoded data */
2068
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2069
drizzle_column_name(column), "xsi:type=", "xs:hexBinary", NULL);
2070
print_blob_as_hex(md_result_file, row[i], length);
2074
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2075
drizzle_column_name(column), NULL);
2076
print_quoted_xml(md_result_file, row[i], length);
2078
fputs("</field>\n", md_result_file);
2080
else if (opt_hex_blob && is_blob && length)
2082
fputs("0x", md_result_file);
2083
print_blob_as_hex(md_result_file, row[i], length);
2086
unescape(md_result_file, row[i], length);
2090
/* change any strings ("inf", "-inf", "nan") into NULL */
2094
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2095
drizzle_column_name(column), NULL);
2096
fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
2098
fputs("</field>\n", md_result_file);
2100
else if (my_isalpha(charset_info, *ptr) ||
2101
(*ptr == '-' && my_isalpha(charset_info, ptr[1])))
2102
fputs("NULL", md_result_file);
2104
fputs(ptr, md_result_file);
2109
/* The field value is NULL */
2111
fputs("NULL", md_result_file);
2113
print_xml_null_tag(md_result_file, "\t\t", "field name=",
2114
drizzle_column_name(column), "\n");
2116
check_io(md_result_file);
2122
fputs("\t</row>\n", md_result_file);
2123
check_io(md_result_file);
2126
if (extended_insert)
2128
uint32_t row_length;
2129
extended_row.append(")");
2130
row_length= 2 + extended_row.length();
2131
if (total_length + row_length < DRIZZLE_MAX_LINE_LENGTH)
2133
total_length+= row_length;
2134
fputc(',',md_result_file); /* Always row break */
2135
fputs(extended_row.c_str(),md_result_file);
2140
fputs(";\n", md_result_file);
2141
row_break=1; /* This is first row */
2143
fputs(insert_pat.c_str(),md_result_file);
2144
fputs(extended_row.c_str(),md_result_file);
2145
total_length= row_length+init_length;
2147
check_io(md_result_file);
2151
fputs(");\n", md_result_file);
2152
check_io(md_result_file);
2156
/* XML - close table tag and supress regular output */
2158
fputs("\t</table_data>\n", md_result_file);
2159
else if (extended_insert && row_break)
2160
fputs(";\n", md_result_file); /* If not empty table */
2161
fflush(md_result_file);
2162
check_io(md_result_file);
2164
/* Moved enable keys to before unlock per bug 15977 */
2165
if (opt_disable_keys)
2167
fprintf(md_result_file,"ALTER TABLE %s ENABLE KEYS;\n",
2169
check_io(md_result_file);
2173
fprintf(md_result_file, "commit;\n");
2174
check_io(md_result_file);
2176
drizzle_result_free(&result);
2186
static char *getTableName(int reset)
2188
static drizzle_result_st result;
2189
static bool have_result= false;
2194
if (drizzleclient_query_with_error_report(&dcon, &result, "SHOW TABLES", false))
2199
if ((row= drizzle_row_next(&result)))
2203
drizzle_row_seek(&result, 0);
2206
drizzle_result_free(&result);
2210
} /* getTableName */
365
2213
static int dump_all_databases()
367
2215
drizzle_row_t row;
368
drizzle_result_st *tableres;
2216
drizzle_result_st tableres;
371
DrizzleDumpDatabase *database;
374
std::cerr << _("-- Retrieving database structures...") << std::endl;
376
/* Blocking the MySQL privilege tables too because we can't import them due to bug#646187 */
377
if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
378
query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')";
380
query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM DATA_DICTIONARY.SCHEMAS WHERE SCHEMA_NAME NOT IN ('information_schema','data_dictionary')";
382
tableres= db_connection->query(query);
383
while ((row= drizzle_row_next(tableres)))
2219
if (drizzleclient_query_with_error_report(&dcon, &tableres, "SHOW DATABASES", false))
2221
while ((row= drizzle_row_next(&tableres)))
385
std::string database_name(row[0]);
386
if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
387
database= new DrizzleDumpDatabaseMySQL(database_name, db_connection);
389
database= new DrizzleDumpDatabaseDrizzle(database_name, db_connection);
391
database->setCollate(row[1]);
392
database_store.push_back(database);
2223
if (dump_all_tables_in_db(row[0]))
394
db_connection->freeResult(tableres);
2226
drizzle_result_free(&tableres);
397
2229
/* dump_all_databases */
400
static int dump_databases(const vector<string> &db_names)
2232
static int dump_databases(char **db_names)
404
DrizzleDumpDatabase *database;
406
for (vector<string>::const_iterator it= db_names.begin(); it != db_names.end(); ++it)
2238
for (db= db_names ; *db ; db++)
409
if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
410
database= new DrizzleDumpDatabaseMySQL(temp, db_connection);
412
database= new DrizzleDumpDatabaseDrizzle(temp, db_connection);
413
database_store.push_back(database);
2240
if (dump_all_tables_in_db(*db))
416
2244
} /* dump_databases */
418
static int dump_selected_tables(const string &db, const vector<string> &table_names)
420
DrizzleDumpDatabase *database;
422
if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
423
database= new DrizzleDumpDatabaseMySQL(db, db_connection);
425
database= new DrizzleDumpDatabaseDrizzle(db, db_connection);
427
if (not database->populateTables(table_names))
430
if (not ignore_errors)
431
maybe_exit(EX_DRIZZLEERR);
434
database_store.push_back(database);
2248
Table Specific database initalization.
2252
qdatabase quoted name of the database
2259
int init_dumping_tables(char *qdatabase)
2265
drizzle_result_st result;
2266
drizzle_return_t ret;
2268
snprintf(qbuf, sizeof(qbuf),
2269
"SHOW CREATE DATABASE IF NOT EXISTS %s",
2272
if (drizzle_query_str(&dcon, &result, qbuf, &ret) == NULL ||
2273
ret != DRIZZLE_RETURN_OK)
2275
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2276
drizzle_result_free(&result);
2278
/* Old server version, dump generic CREATE DATABASE */
2279
if (opt_drop_database)
2280
fprintf(md_result_file,
2281
"\nDROP DATABASE IF EXISTS %s;\n",
2283
fprintf(md_result_file,
2284
"\nCREATE DATABASE IF NOT EXISTS %s;\n",
2289
if (drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
2291
if (opt_drop_database)
2292
fprintf(md_result_file,
2293
"\nDROP DATABASE IF EXISTS %s;\n",
2295
row = drizzle_row_next(&result);
2296
if (row != NULL && row[1])
2298
fprintf(md_result_file,"\n%s;\n",row[1]);
2301
drizzle_result_free(&result);
2305
} /* init_dumping_tables */
2308
static int init_dumping(char *database, int init_func(char*))
2310
drizzle_result_st result;
2311
drizzle_return_t ret;
2313
if (!my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
2316
if (drizzle_select_db(&dcon, &result, database, &ret) == NULL ||
2317
ret != DRIZZLE_RETURN_OK)
2319
DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
2320
return 1; /* If --force */
2322
drizzle_result_free(&result);
2324
if (!path && !opt_xml)
2326
if (opt_databases || opt_alldbs)
2329
length of table name * 2 (if name contains quotes), 2 quotes and 0
2331
char quoted_database_buf[DRIZZLE_MAX_DB_SIZE*2+3];
2332
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
2335
fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
2336
check_io(md_result_file);
2339
/* Call the view or table specific function */
2340
init_func(qdatabase);
2342
fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
2343
check_io(md_result_file);
2346
if (extended_insert)
2347
extended_row.clear();
2349
} /* init_dumping */
2352
/* Return 1 if we should copy the table */
2354
static bool include_table(const char *hash_key, size_t key_size)
2356
string match(hash_key, key_size);
2357
drizzled::hash_set<string>::iterator iter= ignore_table.find(match);
2358
return (iter == ignore_table.end());
2362
static int dump_all_tables_in_db(char *database)
2365
char hash_key[DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2]; /* "db.tablename" */
2367
drizzle_result_st result;
2368
drizzle_return_t ret;
2370
memset(hash_key, 0, DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2);
2371
afterdot= strcpy(hash_key, database) + strlen(database);
2374
if (init_dumping(database, init_dumping_tables))
2377
print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NULL);
2380
if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
2381
ret != DRIZZLE_RETURN_OK)
2383
DB_error(&result, ret, _("when doing refresh"));
2384
/* We shall continue here, if --force was given */
2387
drizzle_result_free(&result);
2389
while ((table= getTableName(0)))
2391
char *end= strcpy(afterdot, table) + strlen(table);
2392
if (include_table(hash_key, end - hash_key))
2394
dump_table(table,database);
2401
fputs("</database>\n", md_result_file);
2402
check_io(md_result_file);
2406
} /* dump_all_tables_in_db */
2410
get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
2411
table name from the server for the table name given on the command line.
2412
we do this because the table name given on the command line may be a
2413
different case (e.g. T1 vs t1)
2416
pointer to the table name
2420
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
2423
drizzle_result_st result;
2425
char query[50 + 2*DRIZZLE_MAX_TABLE_SIZE];
2426
char show_name_buff[FN_REFLEN];
2430
/* Check memory for quote_for_like() */
2431
assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
2432
snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
2433
quote_for_like(old_table_name, show_name_buff));
2435
if (drizzleclient_query_with_error_report(&dcon, &result, query, false))
2438
num_rows= drizzle_result_row_count(&result);
2444
TODO: Return all matching rows
2446
row= drizzle_row_next(&result);
2447
lengths= drizzle_row_field_sizes(&result);
2448
name= strmake_root(root, row[0], lengths[0]);
2450
drizzle_result_free(&result);
2456
static int dump_selected_tables(char *db, char **table_names, int tables)
2459
char **dump_tables, **pos, **end;
2460
drizzle_result_st result;
2461
drizzle_return_t ret;
2464
if (init_dumping(db, init_dumping_tables))
2467
init_alloc_root(&root, 8192, 0);
2468
if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
2469
die(EX_EOM, _("alloc_root failure."));
2471
for (; tables > 0 ; tables-- , table_names++)
2473
/* the table name passed on commandline may be wrong case */
2474
if ((*pos= get_actual_table_name(*table_names, &root)))
2482
free_root(&root, MYF(0));
2484
maybe_die(EX_ILLEGAL_TABLE, _("Couldn't find table: \"%s\""), *table_names);
2485
/* We shall countinue here, if --force was given */
2492
if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
2493
ret != DRIZZLE_RETURN_OK)
2496
free_root(&root, MYF(0));
2497
DB_error(&result, ret, _("when doing refresh"));
2498
/* We shall countinue here, if --force was given */
2501
drizzle_result_free(&result);
2504
print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NULL);
2506
/* Dump each selected table */
2507
for (pos= dump_tables; pos < end; pos++)
2508
dump_table(*pos, db);
2510
free_root(&root, MYF(0));
2515
fputs("</database>\n", md_result_file);
2516
check_io(md_result_file);
437
2519
} /* dump_selected_tables */
439
static int do_flush_tables_read_lock()
2521
static int do_flush_tables_read_lock(drizzle_con_st *drizzle_con)
442
2524
We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
443
2525
will wait but will not stall the whole mysqld, and when the long update is
444
2526
done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
445
FLUSH TABLES is to lower the probability of a stage where both drizzled
2527
FLUSH TABLES is to lower the probability of a stage where both mysqldump
446
2528
and most client connections are stalled. Of course, if a second long
447
2529
update starts between the two FLUSHes, we have that bad stall.
450
db_connection->queryNoResult("FLUSH TABLES");
451
db_connection->queryNoResult("FLUSH TABLES WITH READ LOCK");
456
static int do_unlock_tables()
458
db_connection->queryNoResult("UNLOCK TABLES");
462
static int start_transaction()
464
db_connection->queryNoResult("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ");
465
db_connection->queryNoResult("START TRANSACTION WITH CONSISTENT SNAPSHOT");
2532
( drizzleclient_query_with_error_report(drizzle_con, 0, "FLUSH TABLES", false) ||
2533
drizzleclient_query_with_error_report(drizzle_con, 0,
2534
"FLUSH TABLES WITH READ LOCK", false) );
2537
static int do_unlock_tables(drizzle_con_st *drizzle_con)
2539
return drizzleclient_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES", false);
2542
static int start_transaction(drizzle_con_st *drizzle_con)
2544
return (drizzleclient_query_with_error_report(drizzle_con, 0,
2545
"SET SESSION TRANSACTION ISOLATION "
2546
"LEVEL REPEATABLE READ", false) ||
2547
drizzleclient_query_with_error_report(drizzle_con, 0,
2548
"START TRANSACTION "
2549
"WITH CONSISTENT SNAPSHOT", false));
2553
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
2554
char **err_pos, uint32_t *err_len)
2556
const char *end= x + length;
2561
*err_pos= 0; /* No error yet */
2562
while (end > x && my_isspace(charset_info, end[-1]))
2568
const char *start= x;
2571
const char *pos= start;
2574
for (; pos != end && *pos != ','; pos++) ;
2575
var_len= (uint32_t) (pos - start);
2576
strncpy(buff, start, min((uint32_t)sizeof(buff), var_len+1));
2577
find= find_type(buff, lib, var_len);
2580
*err_pos= (char*) start;
2584
found|= (uint32_t)((int64_t) 1 << (find - 1));
2594
/* Print a value with a prefix on file */
2595
static void print_value(FILE *file, drizzle_result_st *result, drizzle_row_t row,
2596
const char *prefix, const char *name,
2599
drizzle_column_st *column;
2600
drizzle_column_seek(result, 0);
2602
for ( ; (column= drizzle_column_next(result)) ; row++)
2604
if (!strcmp(drizzle_column_name(column),name))
2606
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
2609
fputs(prefix, file);
2611
unescape(file,row[0],(uint32_t) strlen(row[0]));
2613
fputs(row[0], file);
2619
return; /* This shouldn't happen */
2623
* Fetches a row from a result based on a field name
2624
* Returns const char* of the data in that row or NULL if not found
2627
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row, const char *name)
2629
drizzle_column_st *column;
2630
drizzle_column_seek(result, 0);
2632
for ( ; (column= drizzle_column_next(result)) ; row++)
2634
if (!strcmp(drizzle_column_name(column),name))
2636
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
2638
drizzle_column_seek(result, 0);
2643
drizzle_column_seek(result, 0);
2651
Check if we the table is one of the table types that should be ignored:
2652
MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
2653
If the table should be altogether ignored, it returns a true, false if it
2654
should not be ignored. If the user has selected to use INSERT DELAYED, it
2655
sets the value of the bool pointer supports_delayed_inserts to 0 if not
2656
supported, 1 if it is supported.
2660
check_if_ignore_table()
2661
table_name Table name to check
2662
table_type Type of table
2665
drizzle Drizzle connection
2666
verbose Write warning messages
2669
char (bit value) See IGNORE_ values at top
2672
char check_if_ignore_table(const char *table_name, char *table_type)
2674
char result= IGNORE_NONE;
2675
char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
2676
const char *number_of_rows= NULL;
2677
drizzle_result_st res;
2680
/* Check memory for quote_for_like() */
2681
assert(2*sizeof(table_name) < sizeof(show_name_buff));
2682
snprintf(buff, sizeof(buff), "show table status like %s",
2683
quote_for_like(table_name, show_name_buff));
2684
if (drizzleclient_query_with_error_report(&dcon, &res, buff, false))
2688
if (!(row= drizzle_row_next(&res)))
2691
_("Error: Couldn't read status information for table %s\n"),
2693
drizzle_result_free(&res);
2694
return(result); /* assume table is ok */
2698
if ((number_of_rows= fetch_named_row(&res, row, "Rows")) != NULL)
2700
total_rows= strtoul(number_of_rows, NULL, 10);
2704
If the table type matches any of these, we do support delayed inserts.
2705
Note: we do not want to skip dumping this table if if is not one of
2706
these types, but we do want to use delayed inserts in the dump if
2707
the table type is _NOT_ one of these types
2710
strncpy(table_type, row[1], DRIZZLE_MAX_TABLE_SIZE-1);
2713
if (strcmp(table_type,"MyISAM") &&
2714
strcmp(table_type,"ARCHIVE") &&
2715
strcmp(table_type,"HEAP") &&
2716
strcmp(table_type,"MEMORY"))
2717
result= IGNORE_INSERT_DELAYED;
2720
drizzle_result_free(&res);
2726
Get string of comma-separated primary key field names
2729
char *primary_key_fields(const char *table_name)
2730
RETURNS pointer to allocated buffer (must be freed by caller)
2731
table_name quoted table name
2734
Use SHOW KEYS FROM table_name, allocate a buffer to hold the
2735
field names, and then build that string and return the pointer
2738
Returns NULL if there is no PRIMARY or UNIQUE key on the table,
2739
or if there is some failure. It is better to continue to dump
2740
the table unsorted, rather than exit without dumping the data.
2743
static char *primary_key_fields(const char *table_name)
2745
drizzle_result_st res;
2746
drizzle_return_t ret;
2748
/* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
2749
char show_keys_buff[15 + DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
2750
uint32_t result_length= 0;
2752
char buff[DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
2755
snprintf(show_keys_buff, sizeof(show_keys_buff),
2756
"SHOW KEYS FROM %s", table_name);
2757
if (drizzle_query_str(&dcon, &res, show_keys_buff, &ret) == NULL ||
2758
ret != DRIZZLE_RETURN_OK)
2760
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2762
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2763
" records are NOT sorted (%s)\n"),
2764
table_name, drizzle_result_error(&res));
2765
drizzle_result_free(&res);
2769
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2770
" records are NOT sorted (%s)\n"),
2771
table_name, drizzle_con_error(&dcon));
2777
if (drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
2779
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2780
" records are NOT sorted (%s)\n"),
2781
table_name, drizzle_con_error(&dcon));
2786
* Figure out the length of the ORDER BY clause result.
2787
* Note that SHOW KEYS is ordered: a PRIMARY key is always the first
2788
* row, and UNIQUE keys come before others. So we only need to check
2789
* the first key, not all keys.
2791
if ((row= drizzle_row_next(&res)) && atoi(row[1]) == 0)
2796
quoted_field= quote_name(row[4], buff, 0);
2797
result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
2798
} while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1);
2801
/* Build the ORDER BY clause result */
2805
/* result (terminating \0 is already in result_length) */
2806
result= (char *)malloc(result_length + 10);
2809
fprintf(stderr, _("Error: Not enough memory to store ORDER BY clause\n"));
2810
drizzle_result_free(&res);
2813
drizzle_row_seek(&res, 0);
2814
row= drizzle_row_next(&res);
2815
quoted_field= quote_name(row[4], buff, 0);
2816
end= strcpy(result, quoted_field) + strlen(quoted_field);
2817
while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1)
2819
quoted_field= quote_name(row[4], buff, 0);
2820
end+= sprintf(end,",%s",quoted_field);
2824
drizzle_result_free(&res);
469
2829
int main(int argc, char **argv)
475
po::options_description commandline_options(N_("Options used only in command line"));
476
commandline_options.add_options()
477
("all-databases,A", po::value<bool>(&opt_alldbs)->default_value(false)->zero_tokens(),
478
N_("Dump all the databases. This will be same as --databases with all databases selected."))
479
("all-tablespaces,Y", po::value<bool>(&opt_alltspcs)->default_value(false)->zero_tokens(),
480
N_("Dump all the tablespaces."))
481
("complete-insert,c", po::value<bool>(&opt_complete_insert)->default_value(false)->zero_tokens(),
482
N_("Use complete insert statements."))
483
("flush-logs,F", po::value<bool>(&flush_logs)->default_value(false)->zero_tokens(),
484
N_("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"))
485
("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
486
N_("Continue even if we get an sql-error."))
487
("help,?", N_("Display this help message and exit."))
488
("lock-all-tables,x", po::value<bool>(&opt_lock_all_tables)->default_value(false)->zero_tokens(),
489
N_("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."))
490
("single-transaction", po::value<bool>(&opt_single_transaction)->default_value(false)->zero_tokens(),
491
N_("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."))
493
N_("Disable --opt. Disables --add-drop-table, --add-locks, --create-options, ---extended-insert and --disable-keys."))
494
("tables", N_("Overrides option --databases (-B)."))
495
("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(10000),
496
N_("Number of rows before each output progress report (requires --verbose)."))
497
("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
498
N_("Print info about the various stages."))
499
("version,V", N_("Output version information and exit."))
500
("skip-comments", N_("Turn off Comments"))
501
("skip-create", N_("Turn off create-options"))
502
("skip-extended-insert", N_("Turn off extended-insert"))
503
("skip-dump-date",N_( "Turn off dump date at the end of the output"))
504
("no-defaults", N_("Do not read from the configuration files"))
507
po::options_description dump_options(N_("Options specific to the drizzle client"));
508
dump_options.add_options()
509
("add-drop-database", po::value<bool>(&opt_drop_database)->default_value(false)->zero_tokens(),
510
N_("Add a 'DROP DATABASE' before each create."))
511
("skip-drop-table", N_("Do not add a 'drop table' before each create."))
512
("compact", po::value<bool>(&opt_compact)->default_value(false)->zero_tokens(),
513
N_("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"))
514
("databases,B", po::value<bool>(&opt_databases)->default_value(false)->zero_tokens(),
515
N_("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."))
516
("skip-disable-keys,K",
517
N_("'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will not be put in the output."))
518
("ignore-table", po::value<string>(),
519
N_("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"))
520
("insert-ignore", po::value<bool>(&opt_ignore)->default_value(false)->zero_tokens(),
521
N_("Insert rows with INSERT IGNORE."))
522
("no-autocommit", po::value<bool>(&opt_autocommit)->default_value(false)->zero_tokens(),
523
N_("Wrap a table's data in START TRANSACTION/COMMIT statements."))
524
("no-create-db,n", po::value<bool>(&opt_create_db)->default_value(false)->zero_tokens(),
525
N_("'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."))
526
("no-data,d", po::value<bool>(&opt_no_data)->default_value(false)->zero_tokens(),
527
N_("No row information."))
528
("replace", po::value<bool>(&opt_replace_into)->default_value(false)->zero_tokens(),
529
N_("Use REPLACE INTO instead of INSERT INTO."))
530
("destination-type", po::value<string>()->default_value("stdout"),
531
N_("Where to send output to (stdout|database"))
532
("destination-host", po::value<string>(&opt_destination_host)->default_value("localhost"),
533
N_("Hostname for destination db server (requires --destination-type=database)"))
534
("destination-port", po::value<uint16_t>(&opt_destination_port)->default_value(4427),
535
N_("Port number for destination db server (requires --destination-type=database)"))
536
("destination-user", po::value<string>(&opt_destination_user),
537
N_("User name for destination db server (resquires --destination-type=database)"))
538
("destination-password", po::value<string>(&opt_destination_password),
539
N_("Password for destination db server (requires --destination-type=database)"))
540
("destination-database", po::value<string>(&opt_destination_database),
541
N_("The database in the destination db server (requires --destination-type=database, not for use with --all-databases)"))
544
po::options_description client_options(N_("Options specific to the client"));
545
client_options.add_options()
546
("host,h", po::value<string>(¤t_host)->default_value("localhost"),
547
N_("Connect to host."))
548
("password,P", po::value<string>(&password)->default_value(PASSWORD_SENTINEL),
549
N_("Password to use when connecting to server. If password is not given it's solicited on the tty."))
550
("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
551
N_("Port number to use for connection."))
552
("user,u", po::value<string>(¤t_user)->default_value(""),
553
N_("User for login if not current user."))
554
("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
555
N_("The protocol of connection (mysql or drizzle)."))
558
po::options_description hidden_options(N_("Hidden Options"));
559
hidden_options.add_options()
560
("database-used", po::value<vector<string> >(), N_("Used to select the database"))
561
("Table-used", po::value<vector<string> >(), N_("Used to select the tables"))
564
po::options_description all_options(N_("Allowed Options + Hidden Options"));
565
all_options.add(commandline_options).add(dump_options).add(client_options).add(hidden_options);
567
po::options_description long_options(N_("Allowed Options"));
568
long_options.add(commandline_options).add(dump_options).add(client_options);
570
std::string system_config_dir_dump(SYSCONFDIR);
571
system_config_dir_dump.append("/drizzle/drizzledump.cnf");
573
std::string system_config_dir_client(SYSCONFDIR);
574
system_config_dir_client.append("/drizzle/client.cnf");
576
std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
578
if (user_config_dir.compare(0, 2, "~/") == 0)
581
homedir= getenv("HOME");
583
user_config_dir.replace(0, 1, homedir);
586
po::positional_options_description p;
587
p.add("database-used", 1);
588
p.add("Table-used",-1);
590
md_result_file= stdout;
592
po::variables_map vm;
594
// Disable allow_guessing
595
int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
597
po::store(po::command_line_parser(argc, argv).style(style).
598
options(all_options).positional(p).
599
extra_parser(parse_password_arg).run(), vm);
601
if (! vm.count("no-defaults"))
603
std::string user_config_dir_dump(user_config_dir);
604
user_config_dir_dump.append("/drizzle/drizzledump.cnf");
606
std::string user_config_dir_client(user_config_dir);
607
user_config_dir_client.append("/drizzle/client.cnf");
609
ifstream user_dump_ifs(user_config_dir_dump.c_str());
610
po::store(parse_config_file(user_dump_ifs, dump_options), vm);
612
ifstream user_client_ifs(user_config_dir_client.c_str());
613
po::store(parse_config_file(user_client_ifs, client_options), vm);
615
ifstream system_dump_ifs(system_config_dir_dump.c_str());
616
po::store(parse_config_file(system_dump_ifs, dump_options), vm);
618
ifstream system_client_ifs(system_config_dir_client.c_str());
619
po::store(parse_config_file(system_client_ifs, client_options), vm);
624
if ((not vm.count("database-used") && not vm.count("Table-used")
625
&& not opt_alldbs && path.empty())
626
|| (vm.count("help")) || vm.count("version"))
628
printf(_("Drizzledump %s build %s, for %s-%s (%s)\n"),
629
drizzle_version(), VERSION, HOST_VENDOR, HOST_OS, HOST_CPU);
630
if (vm.count("version"))
633
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"));
634
puts(_("Dumps definitions and data from a Drizzle database server"));
635
printf(_("Usage: %s [OPTIONS] database [tables]\n"), progname.c_str());
636
printf(_("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n"),
638
printf(_("OR %s [OPTIONS] --all-databases [OPTIONS]\n"), progname.c_str());
639
cout << long_options;
640
if (vm.count("help"))
646
/* Inverted Booleans */
648
opt_drop= (vm.count("skip-drop-table")) ? false : true;
649
opt_comments= (vm.count("skip-comments")) ? false : true;
650
extended_insert= (vm.count("skip-extended-insert")) ? false : true;
651
opt_dump_date= (vm.count("skip-dump-date")) ? false : true;
652
opt_disable_keys= (vm.count("skip-disable-keys")) ? false : true;
653
opt_quoted= (vm.count("skip-quote-names")) ? false : true;
655
if (vm.count("protocol"))
657
std::transform(opt_protocol.begin(), opt_protocol.end(),
658
opt_protocol.begin(), ::tolower);
660
if (not opt_protocol.compare("mysql"))
661
use_drizzle_protocol=false;
662
else if (not opt_protocol.compare("drizzle"))
663
use_drizzle_protocol=true;
666
cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
671
if (vm.count("port"))
673
/* If the port number is > 65535 it is not a valid port
674
* This also helps with potential data loss casting unsigned long to a
677
if (opt_drizzle_port > 65535)
679
fprintf(stderr, _("Value supplied for port is not valid.\n"));
684
if(vm.count("password"))
686
if (!opt_password.empty())
687
opt_password.erase();
688
if (password == PASSWORD_SENTINEL)
694
opt_password= password;
708
if (vm.count("skip-opt"))
710
extended_insert= opt_drop= create_options= 0;
716
opt_comments= opt_drop= opt_disable_keys= 0;
721
extended_insert= opt_drop= create_options= 1;
725
if (vm.count("tables"))
727
opt_databases= false;
730
if (vm.count("ignore-table"))
732
if (!strchr(vm["ignore-table"].as<string>().c_str(), '.'))
734
fprintf(stderr, _("Illegal use of option --ignore-table=<database>.<table>\n"));
735
exit(EXIT_ARGUMENT_INVALID);
737
string tmpptr(vm["ignore-table"].as<string>());
738
ignore_table.insert(tmpptr);
741
if (vm.count("skip-create"))
743
opt_create_db= opt_no_create_info= create_options= false;
746
exit_code= get_options();
2832
MY_INIT("drizzledump");
2833
drizzle_result_st result;
2835
compatible_mode_normal_str[0]= 0;
2837
exit_code= get_options(&argc, &argv);
749
2840
free_resources();
750
2841
exit(exit_code);
754
db_connection = new DrizzleDumpConnection(current_host, opt_drizzle_port,
755
current_user, opt_password, use_drizzle_protocol);
757
catch (std::exception&)
759
maybe_exit(EX_DRIZZLEERR);
762
if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
763
db_connection->queryNoResult("SET NAMES 'utf8'");
765
if (vm.count("destination-type"))
767
string tmp_destination(vm["destination-type"].as<string>());
768
if (tmp_destination.compare("database") == 0)
769
opt_destination= DESTINATION_DB;
770
else if (tmp_destination.compare("stdout") == 0)
771
opt_destination= DESTINATION_STDOUT;
773
exit(EXIT_ARGUMENT_INVALID);
777
if (path.empty() && vm.count("database-used"))
779
string database_used= *vm["database-used"].as< vector<string> >().begin();
780
write_header((char *)database_used.c_str());
783
if ((opt_lock_all_tables) && do_flush_tables_read_lock())
785
if (opt_single_transaction && start_transaction())
2844
if (connect_to_db(current_host, current_user, opt_password))
2847
exit(EX_DRIZZLEERR);
2850
write_header(md_result_file, *argv);
2852
if ((opt_lock_all_tables) && do_flush_tables_read_lock(&dcon))
2854
if (opt_single_transaction && start_transaction(&dcon))
787
2856
if (opt_lock_all_tables)
788
db_connection->queryNoResult("FLUSH LOGS");
789
if (opt_single_transaction && do_unlock_tables()) /* unlock but no commit! */
2858
if (drizzleclient_query_with_error_report(&dcon, &result, "FLUSH LOGS", false))
2860
drizzle_result_free(&result);
2861
flush_logs= 0; /* not anymore; that would not be sensible */
2863
if (opt_single_transaction && do_unlock_tables(&dcon)) /* unlock but no commit! */
794
2868
dump_all_databases();
797
if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
2870
else if (argc > 1 && !opt_databases)
799
string database_used= *vm["database-used"].as< vector<string> >().begin();
800
2872
/* Only one database and selected table(s) */
801
dump_selected_tables(database_used, vm["Table-used"].as< vector<string> >());
804
if (vm.count("Table-used") and opt_databases)
806
vector<string> database_used= vm["database-used"].as< vector<string> >();
807
vector<string> table_used= vm["Table-used"].as< vector<string> >();
809
for (vector<string>::iterator it= table_used.begin();
810
it != table_used.end();
813
database_used.insert(database_used.end(), *it);
816
dump_databases(database_used);
820
if (vm.count("database-used") && ! vm.count("Table-used"))
822
dump_databases(vm["database-used"].as< vector<string> >());
826
if (opt_destination == DESTINATION_STDOUT)
2873
dump_selected_tables(*argv, (argv + 1), (argc - 1));
2877
dump_databases(argv);
831
2880
/* ensure dumped data flushed */
832
2881
if (md_result_file && fflush(md_result_file))