34
32
#include "client_priv.h"
35
#include "drizzled/internal/my_sys.h"
36
#include "drizzled/internal/m_string.h"
37
#include "drizzled/charset_info.h"
37
38
#include <stdarg.h>
38
#include <boost/unordered_set.hpp>
39
#include <drizzled/unordered_set.h>
39
40
#include <algorithm>
41
42
#include <drizzled/gettext.h>
42
#include <drizzled/configmake.h>
43
44
#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
46
using namespace std;
52
47
using namespace drizzled;
53
namespace po= boost::program_options;
58
52
#define EX_DRIZZLEERR 2
53
#define EX_CONSCHECK 3
59
55
#define EX_EOF 5 /* ferror for output file was got */
62
static bool use_drizzle_protocol= false;
63
bool ignore_errors= false;
56
#define EX_ILLEGAL_TABLE 6
57
#define EX_TABLE_STATUS 7
59
/* index into 'show fields from table' */
61
#define SHOW_FIELDNAME 0
64
#define SHOW_DEFAULT 4
67
/* Size of buffer for dump's select query */
68
#define QUERY_LENGTH 1536
69
#define DRIZZLE_MAX_LINE_LENGTH 1024*1024L-1025
71
/* ignore table flags */
72
#define IGNORE_NONE 0x00 /* no ignore */
73
#define IGNORE_DATA 0x01 /* don't dump data for this table */
74
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
76
static void add_load_option(string &str, const char *option,
77
const char *option_value);
78
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
79
char **err_pos, uint32_t *err_len);
81
static void field_escape(string &in, const char *from);
82
static bool verbose= false;
83
static bool opt_no_create_info= false;
84
static bool opt_no_data= false;
85
static bool opt_mysql= false;
86
static bool quick= true;
87
static bool extended_insert= true;
88
static bool ignore_errors= false;
64
89
static bool flush_logs= false;
90
static bool opt_drop= true;
91
static bool opt_keywords= false;
92
static bool opt_compress= false;
93
static bool opt_delayed= false;
65
94
static bool create_options= true;
66
95
static bool opt_quoted= false;
67
bool opt_databases= false;
68
bool opt_alldbs= false;
96
static bool opt_databases= false;
97
static bool opt_alldbs= false;
98
static bool opt_create_db= false;
69
99
static bool opt_lock_all_tables= false;
100
static bool opt_set_charset= false;
70
101
static bool opt_dump_date= true;
71
bool opt_autocommit= false;
102
static bool opt_autocommit= false;
103
static bool opt_disable_keys= true;
104
static bool opt_xml= false;
72
105
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;
106
static bool opt_comments= false;
107
static bool opt_compact= false;
108
static bool opt_hex_blob= false;
109
static bool opt_order_by_primary=false;
110
static bool opt_ignore= false;
111
static bool opt_complete_insert= false;
112
static bool opt_drop_database= false;
113
static bool opt_replace_into= false;
114
static bool opt_routines= false;
115
static bool opt_alltspcs= false;
116
static uint32_t show_progress_size= 0;
117
static uint64_t total_rows= 0;
118
static drizzle_st drizzle;
119
static drizzle_con_st dcon;
86
120
static string insert_pat;
121
static char *opt_password= NULL;
122
static char *current_user= NULL;
123
static char *current_host= NULL;
124
static char *path= NULL;
125
static char *fields_terminated= NULL;
126
static char *lines_terminated= NULL;
127
static char *enclosed= NULL;
128
static char *opt_enclosed= NULL;
129
static char *escaped= NULL;
130
static char *where= NULL;
131
static char *order_by= NULL;
132
static char *opt_compatible_mode_str= NULL;
133
static char *err_ptr= NULL;
134
static char **defaults_argv= NULL;
135
static char compatible_mode_normal_str[255];
136
static uint32_t opt_compatible_mode= 0;
87
137
static uint32_t opt_drizzle_port= 0;
88
138
static int first_error= 0;
89
139
static string extended_row;
90
140
FILE *md_result_file= 0;
91
141
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);
143
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
145
static const char *compatible_mode_names[]=
147
"MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
148
"MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
152
static TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
153
"", compatible_mode_names, NULL};
155
unordered_set<string> ignore_table;
157
static struct option my_long_options[] =
159
{"all", 'a', "Deprecated. Use --create-options instead.",
160
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
162
{"all-databases", 'A',
163
"Dump all the databases. This will be same as --databases with all databases selected.",
164
(char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
166
{"all-tablespaces", 'Y',
167
"Dump all the tablespaces.",
168
(char**) &opt_alltspcs, (char**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
170
{"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
171
(char**) &opt_drop_database, (char**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
173
{"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
174
(char**) &opt_drop, (char**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
176
{"allow-keywords", OPT_KEYWORDS,
177
"Allow creation of column names that are keywords.", (char**) &opt_keywords,
178
(char**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
179
{"comments", 'i', "Write additional information.",
180
(char**) &opt_comments, (char**) &opt_comments, 0, GET_BOOL, NO_ARG,
182
{"compatible", OPT_COMPATIBLE,
183
"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.",
184
(char**) &opt_compatible_mode_str, (char**) &opt_compatible_mode_str, 0,
185
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
186
{"compact", OPT_COMPACT,
187
"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",
188
(char**) &opt_compact, (char**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
190
{"complete-insert", 'c', "Use complete insert statements.",
191
(char**) &opt_complete_insert, (char**) &opt_complete_insert, 0, GET_BOOL,
192
NO_ARG, 0, 0, 0, 0, 0, 0},
193
{"compress", 'C', "Use compression in server/client protocol.",
194
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
196
{"create-options", OPT_CREATE_OPTIONS,
197
"Include all DRIZZLE specific create options.",
198
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
201
"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.",
202
(char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
204
{"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
205
(char**) &opt_delayed, (char**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
207
{"disable-keys", 'K',
208
"'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will be put in the output.", (char**) &opt_disable_keys,
209
(char**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
210
{"extended-insert", 'e',
211
"Allows utilization of the new, much faster INSERT syntax.",
212
(char**) &extended_insert, (char**) &extended_insert, 0, GET_BOOL, NO_ARG,
214
{"fields-terminated-by", OPT_FTB,
215
"Fields in the textfile are terminated by ...", (char**) &fields_terminated,
216
(char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
217
{"fields-enclosed-by", OPT_ENC,
218
"Fields in the importfile are enclosed by ...", (char**) &enclosed,
219
(char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
220
{"fields-optionally-enclosed-by", OPT_O_ENC,
221
"Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
222
(char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
223
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
224
(char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
225
{"flush-logs", 'F', "Flush logs file in server before starting dump. "
226
"Note that if you dump many databases at once (using the option "
227
"--databases= or --all-databases), the logs will be flushed for "
228
"each database dumped. The exception is when using --lock-all-tables "
229
"in this case the logs will be flushed only once, corresponding "
230
"to the moment all tables are locked. So if you want your dump and "
231
"the log flush to happen at the same exact moment you should use "
232
"--lock-all-tables or --flush-logs",
233
(char**) &flush_logs, (char**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
235
{"force", 'f', "Continue even if we get an sql-error.",
236
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG,
238
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
239
NO_ARG, 0, 0, 0, 0, 0, 0},
240
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
241
"VARBINARY, BLOB) in hexadecimal format.",
242
(char**) &opt_hex_blob, (char**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
243
{"host", 'h', "Connect to host.", (char**) ¤t_host,
244
(char**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
245
{"ignore-table", OPT_IGNORE_TABLE,
246
"Do not dump the specified table. To specify more than one table to ignore, "
247
"use the directive multiple times, once for each table. Each table must "
248
"be specified with both database and table names, e.g. --ignore-table=database.table",
249
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
250
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
251
(char**) &opt_ignore, (char**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
253
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
254
(char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
255
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
256
{"lock-all-tables", 'x', "Locks all tables across all databases. This "
257
"is achieved by taking a global read lock for the duration of the whole "
258
"dump. Automatically turns --single-transaction and --lock-tables off.",
259
(char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
261
{"mysql", 'm', N_("Use MySQL Protocol."),
262
(char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
264
{"no-autocommit", OPT_AUTOCOMMIT,
265
"Wrap tables with autocommit/commit statements.",
266
(char**) &opt_autocommit, (char**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
268
{"no-create-db", 'n',
269
"'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.}.",
270
(char**) &opt_create_db, (char**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
272
{"no-create-info", 't', "Don't write table creation info.",
273
(char**) &opt_no_create_info, (char**) &opt_no_create_info, 0, GET_BOOL,
274
NO_ARG, 0, 0, 0, 0, 0, 0},
275
{"no-data", 'd', "No row information.", (char**) &opt_no_data,
276
(char**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
277
{"no-set-names", 'N',
278
"Deprecated. Use --skip-set-charset instead.",
279
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
280
{"opt", OPT_OPTIMIZE,
281
"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.",
282
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
283
{"order-by-primary", OPT_ORDER_BY_PRIMARY,
284
"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.",
285
(char**) &opt_order_by_primary, (char**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
287
"Password to use when connecting to server. If password is not given it's solicited on the tty.",
288
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
289
{"port", 'p', "Port number to use for connection.",
290
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
291
{"quick", 'q', "Don't buffer query, dump directly to stdout.",
292
(char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
293
{"quote-names",'Q', "Quote table and column names with backticks (`).",
294
(char**) &opt_quoted, (char**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
296
{"replace", OPT_DRIZZLE_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
297
(char**) &opt_replace_into, (char**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
300
"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).",
301
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
302
{"routines", 'R', "Dump stored routines (functions and procedures).",
303
(char**) &opt_routines, (char**) &opt_routines, 0, GET_BOOL,
304
NO_ARG, 0, 0, 0, 0, 0, 0},
305
{"single-transaction", OPT_TRANSACTION,
306
"Creates a consistent snapshot by dumping all tables in a single "
307
"transaction. Works ONLY for tables stored in storage engines which "
308
"support multiversioning (currently only InnoDB does); the dump is NOT "
309
"guaranteed to be consistent for other storage engines. "
310
"While a --single-transaction dump is in process, to ensure a valid "
311
"dump file (correct table contents), no other "
312
"connection should use the following statements: ALTER TABLE, DROP "
313
"TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
314
"isolated from them. Option automatically turns off --lock-tables.",
315
(char**) &opt_single_transaction, (char**) &opt_single_transaction, 0,
316
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
317
{"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
318
(char**) &opt_dump_date, (char**) &opt_dump_date, 0,
319
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
320
{"skip-opt", OPT_SKIP_OPTIMIZATION,
321
"Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
322
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
324
"Creates tab separated textfile for each table to given path. (creates .sql and .txt files). NOTE: This only works if drizzledump is run on the same machine as the drizzled daemon.",
325
(char**) &path, (char**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
326
{"tables", OPT_TABLES, "Overrides option --databases (-B).",
327
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
328
{"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of rows before each output progress report (requires --verbose)."),
329
(char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
330
10000, 0, 0, 0, 0, 0},
331
{"user", 'u', "User for login if not current user.",
332
(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);
312
754
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
315
fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
757
fprintf(stderr, "%s: %s\n", internal::my_progname, buffer);
318
760
ignore_errors= 0; /* force the exit */
319
761
maybe_exit(error_num);
766
Prints out an error message and maybe kills the process.
770
error_num - process return value
771
fmt_reason - a format string for use by vsnprintf.
772
... - variable arguments for above fmt_reason string
775
This call prints out the formatted error message to stderr and then
776
terminates the process, unless the --force command line option is used.
778
This call should be used for non-fatal errors (such as database
779
errors) that the code may still be able to continue to the next unit
783
static void maybe_die(int error_num, const char* fmt_reason, ...)
787
va_start(args,fmt_reason);
788
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
791
fprintf(stderr, "%s: %s\n", internal::my_progname, buffer);
794
maybe_exit(error_num);
800
Sends a query to server, optionally reads result, prints error message if
804
drizzleclient_query_with_error_report()
805
drizzle_con connection to use
806
res if non zero, result will be put there with
807
drizzleclient_store_result()
808
query query to send to server
811
0 query sending and (if res!=0) result reading went ok
815
static int drizzleclient_query_with_error_report(drizzle_con_st *con,
816
drizzle_result_st *result,
817
const char *query_str,
820
drizzle_return_t ret;
822
if (drizzle_query_str(con, result, query_str, &ret) == NULL ||
823
ret != DRIZZLE_RETURN_OK)
825
if (ret == DRIZZLE_RETURN_ERROR_CODE)
827
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
828
query_str, drizzle_result_error(result),
829
drizzle_result_error_code(result));
830
drizzle_result_free(result);
834
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
835
query_str, drizzle_con_error(con), ret);
841
ret= drizzle_column_buffer(result);
843
ret= drizzle_result_buffer(result);
844
if (ret != DRIZZLE_RETURN_OK)
846
drizzle_result_free(result);
847
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
848
query_str, drizzle_con_error(con), ret);
856
Open a new .sql file to dump the table or view into
859
open_sql_file_for_table
860
name name of the table or view
863
0 Failed to open file
864
> 0 Handle of the open file
866
static FILE* open_sql_file_for_table(const char* table)
869
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
870
internal::convert_dirname(tmp_path,path,NULL);
871
res= fopen(internal::fn_format(filename, table, tmp_path, ".sql", 4), "w");
322
877
static void free_resources(void)
324
879
if (md_result_file && md_result_file != stdout)
325
880
fclose(md_result_file);
326
opt_password.erase();
883
internal::free_defaults(defaults_argv);
330
void maybe_exit(int error)
888
static void maybe_exit(int error)
332
890
if (!first_error)
333
891
first_error= error;
334
892
if (ignore_errors)
336
delete db_connection;
337
delete destination_connection;
894
drizzle_con_free(&dcon);
895
drizzle_free(&drizzle);
338
896
free_resources();
902
db_connect -- connects to the host and selects DB.
905
static int connect_to_db(char *host, char *user,char *passwd)
907
drizzle_return_t ret;
909
verbose_msg(_("-- Connecting to %s...\n"), host ? host : "localhost");
910
drizzle_create(&drizzle);
911
drizzle_con_create(&drizzle, &dcon);
912
drizzle_con_set_tcp(&dcon, host, opt_drizzle_port);
913
drizzle_con_set_auth(&dcon, user, passwd);
915
drizzle_con_add_options(&dcon, DRIZZLE_CON_MYSQL);
916
ret= drizzle_con_connect(&dcon);
917
if (ret != DRIZZLE_RETURN_OK)
919
DB_error(NULL, ret, "when trying to connect");
924
} /* connect_to_db */
928
** dbDisconnect -- disconnects from the host.
930
static void dbDisconnect(char *host)
932
verbose_msg(_("-- Disconnecting from %s...\n"), host ? host : "localhost");
933
drizzle_con_free(&dcon);
934
drizzle_free(&drizzle);
938
static void unescape(FILE *file,char *pos,uint32_t length)
942
if (!(tmp=(char*) malloc(length*2+1)))
943
die(EX_DRIZZLEERR, _("Couldn't allocate memory"));
945
drizzle_escape_string(tmp, pos, length);
955
static bool test_if_special_chars(const char *str)
957
for ( ; *str ; str++)
958
if (!my_isvar(charset_info,*str) && *str != '$')
961
} /* test_if_special_chars */
966
quote_name(name, buff, force)
968
Quotes char string, taking into account compatible mode
972
name Unquoted string containing that which will be quoted
973
buff The buffer that contains the quoted value, also returned
974
force Flag to make it ignore 'test_if_special_chars'
981
static char *quote_name(const char *name, char *buff, bool force)
986
if (!force && !opt_quoted && !test_if_special_chars(name))
1002
Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
1006
name name of the table
1007
buff quoted name of the table
1010
Quote \, _, ' and % characters
1012
Note: Because DRIZZLE uses the C escape syntax in strings
1013
(for example, '\n' to represent newline), you must double
1014
any '\' that you use in your LIKE strings. For example, to
1015
search for '\n', specify it as '\\n'. To search for '\', specify
1016
it as '\\\\' (the backslashes are stripped once by the parser
1017
and another time when the pattern match is done, leaving a
1018
single backslash to be matched).
1020
Example: "t\1" => "t\\\\1"
1023
static char *quote_for_like(const char *name, char *buff)
1035
else if (*name == '\'' || *name == '_' || *name == '%')
1046
Quote and print a string.
1050
xml_file - output file
1051
str - string to print
1055
Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1058
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
1062
for (end= str + len; str != end; str++)
1066
fputs("<", xml_file);
1069
fputs(">", xml_file);
1072
fputs("&", xml_file);
1075
fputs(""", xml_file);
1078
fputc(*str, xml_file);
1087
Print xml tag. Optionally add attribute(s).
1090
print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
1091
..., attribute_name_n, attribute_value_n, NULL)
1092
xml_file - output file
1093
sbeg - line beginning
1094
line_end - line ending
1095
tag_name - XML tag name.
1096
first_attribute_name - tag and first attribute
1097
first_attribute_value - (Implied) value of first attribute
1098
attribute_name_n - attribute n
1099
attribute_value_n - value of attribute n
1102
Print XML tag with any number of attribute="value" pairs to the xml_file.
1105
sbeg<tag_name first_attribute_name="first_attribute_value" ...
1106
attribute_name_n="attribute_value_n">send
1108
Additional arguments must be present in attribute/value pairs.
1109
The last argument should be the null character pointer.
1110
All attribute_value arguments MUST be NULL terminated strings.
1111
All attribute_value arguments will be quoted before output.
1114
static void print_xml_tag(FILE * xml_file, const char* sbeg,
1115
const char* line_end,
1116
const char* tag_name,
1117
const char* first_attribute_name, ...)
1120
const char *attribute_name, *attribute_value;
1122
fputs(sbeg, xml_file);
1123
fputc('<', xml_file);
1124
fputs(tag_name, xml_file);
1126
va_start(arg_list, first_attribute_name);
1127
attribute_name= first_attribute_name;
1128
while (attribute_name != NULL)
1130
attribute_value= va_arg(arg_list, char *);
1131
assert(attribute_value != NULL);
1133
fputc(' ', xml_file);
1134
fputs(attribute_name, xml_file);
1135
fputc('\"', xml_file);
1137
print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
1138
fputc('\"', xml_file);
1140
attribute_name= va_arg(arg_list, char *);
1144
fputc('>', xml_file);
1145
fputs(line_end, xml_file);
1151
Print xml tag with for a field that is null
1154
print_xml_null_tag()
1155
xml_file - output file
1156
sbeg - line beginning
1157
stag_atr - tag and attribute
1158
sval - value of attribute
1159
line_end - line ending
1162
Print tag with one attribute to the xml_file. Format is:
1163
<stag_atr="sval" xsi:nil="true"/>
1165
sval MUST be a NULL terminated string.
1166
sval string will be qouted before output.
1169
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
1170
const char* stag_atr, const char* sval,
1171
const char* line_end)
1173
fputs(sbeg, xml_file);
1174
fputs("<", xml_file);
1175
fputs(stag_atr, xml_file);
1176
fputs("\"", xml_file);
1177
print_quoted_xml(xml_file, sval, strlen(sval));
1178
fputs("\" xsi:nil=\"true\" />", xml_file);
1179
fputs(line_end, xml_file);
1185
Print xml tag with many attributes.
1189
xml_file - output file
1190
row_name - xml tag name
1191
tableRes - query result
1195
Print tag with many attribute to the xml_file. Format is:
1196
\t\t<row_name Atr1="Val1" Atr2="Val2"... />
1198
All atributes and values will be quoted before output.
1201
static void print_xml_row(FILE *xml_file, const char *row_name,
1202
drizzle_result_st *tableRes, drizzle_row_t *row)
1205
drizzle_column_st *column;
1206
size_t *lengths= drizzle_row_field_sizes(tableRes);
1208
fprintf(xml_file, "\t\t<%s", row_name);
1210
drizzle_column_seek(tableRes, 0);
1211
for (i= 0; (column= drizzle_column_next(tableRes)); i++)
1215
fputc(' ', xml_file);
1216
print_quoted_xml(xml_file, drizzle_column_name(column),
1217
strlen(drizzle_column_name(column)));
1218
fputs("=\"", xml_file);
1219
print_quoted_xml(xml_file, (*row)[i], lengths[i]);
1220
fputc('"', xml_file);
1224
fputs(" />\n", xml_file);
1230
Print hex value for blob data.
1234
output_file - output file
1235
str - string to print
1239
Print hex value for blob data.
1242
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
1244
/* sakaik got the idea to to provide blob's in hex notation. */
1245
const char *ptr= str, *end= ptr + len;
1246
for (; ptr < end ; ptr++)
1247
fprintf(output_file, "%02X", *((unsigned char *)ptr));
1248
check_io(output_file);
1252
get_table_structure -- retrievs database structure, prints out corresponding
1253
CREATE statement and fills out insert_pat if the table is the type we will
1259
table_type - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
1260
ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1261
num_fields - number of fields in the table
1264
true if success, false if error
1267
static bool get_table_structure(char *table, char *db, char *table_type,
1268
char *ignore_flag, uint64_t *num_fields)
1270
bool init=0, delayed, write_data, complete_insert;
1271
char *result_table, *opt_quoted_table;
1272
const char *insert_option;
1273
char name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE+3];
1274
char table_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+3];
1275
char table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3];
1276
char query_buff[QUERY_LENGTH];
1277
FILE *sql_file= md_result_file;
1278
drizzle_result_st result;
1281
*ignore_flag= check_if_ignore_table(table, table_type);
1283
delayed= opt_delayed;
1284
if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
1287
verbose_msg(_("-- Warning: Unable to use delayed inserts for table '%s' "
1288
"because it's of type %s\n"), table, table_type);
1292
if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1294
complete_insert= opt_complete_insert;
1298
insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
1299
delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
1301
verbose_msg(_("-- Retrieving table structure for table %s...\n"), table);
1303
result_table= quote_name(table, table_buff, 1);
1304
opt_quoted_table= quote_name(table, table_buff2, 0);
1306
if (opt_order_by_primary)
1309
order_by= primary_key_fields(result_table);
1314
/* using SHOW CREATE statement */
1315
if (!opt_no_create_info)
1317
/* Make an sql-file, if path was given iow. option -T was given */
1318
char buff[20+FN_REFLEN];
1319
const drizzle_column_st *column;
1321
snprintf(buff, sizeof(buff), "show create table %s", result_table);
1323
if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1328
if (!(sql_file= open_sql_file_for_table(table)))
1330
drizzle_result_free(&result);
1334
write_header(sql_file, db);
1336
if (!opt_xml && opt_comments)
1338
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1345
Even if the "table" is a view, we do a DROP TABLE here.
1347
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
1351
column= drizzle_column_index(&result, 0);
1353
row= drizzle_row_next(&result);
1355
fprintf(sql_file, "%s;\n", row[1]);
1358
drizzle_result_free(&result);
1361
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1364
if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
1372
If write_data is true, then we build up insert statements for
1373
the table's data. Note: in subsequent lines of code, this test
1374
will have to be performed each time we are appending to
1379
if (opt_replace_into)
1380
insert_pat.append("REPLACE ");
1382
insert_pat.append("INSERT ");
1383
insert_pat.append(insert_option);
1384
insert_pat.append("INTO ");
1385
insert_pat.append(opt_quoted_table);
1386
if (complete_insert)
1388
insert_pat.append(" (");
1392
insert_pat.append(" VALUES ");
1393
if (!extended_insert)
1394
insert_pat.append("(");
1398
while ((row= drizzle_row_next(&result)))
1400
if (complete_insert)
1404
insert_pat.append(", ");
1407
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1410
*num_fields= drizzle_result_row_count(&result);
1411
drizzle_result_free(&result);
1415
verbose_msg(_("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n"),
1416
internal::my_progname, drizzle_con_error(&dcon));
1418
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1420
if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
1423
/* Make an sql-file, if path was given iow. option -T was given */
1424
if (!opt_no_create_info)
1428
if (!(sql_file= open_sql_file_for_table(table)))
1430
drizzle_result_free(&result);
1433
write_header(sql_file, db);
1435
if (!opt_xml && opt_comments)
1436
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1439
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1441
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
1443
print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
1450
if (opt_replace_into)
1451
insert_pat.append("REPLACE ");
1453
insert_pat.append("INSERT ");
1454
insert_pat.append(insert_option);
1455
insert_pat.append("INTO ");
1456
insert_pat.append(result_table);
1457
if (complete_insert)
1458
insert_pat.append(" (");
1461
insert_pat.append(" VALUES ");
1462
if (!extended_insert)
1463
insert_pat.append("(");
1467
while ((row= drizzle_row_next(&result)))
1469
size_t *lengths= drizzle_row_field_sizes(&result);
1472
if (!opt_xml && !opt_no_create_info)
1474
fputs(",\n",sql_file);
1477
if (complete_insert)
1478
insert_pat.append(", ");
1481
if (complete_insert)
1482
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1483
if (!opt_no_create_info)
1487
print_xml_row(sql_file, "field", &result, &row);
1492
fprintf(sql_file, " %s.%s %s", result_table,
1493
quote_name(row[SHOW_FIELDNAME],name_buff, 0),
1496
fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
1499
if (row[SHOW_DEFAULT])
1501
fputs(" DEFAULT ", sql_file);
1502
unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1504
if (!row[SHOW_NULL][0])
1505
fputs(" NOT NULL", sql_file);
1506
if (row[SHOW_EXTRA][0])
1507
fprintf(sql_file, " %s",row[SHOW_EXTRA]);
1511
*num_fields= drizzle_result_row_count(&result);
1512
drizzle_result_free(&result);
1514
if (!opt_no_create_info)
1516
/* Make an sql-file, if path was given iow. option -T was given */
1517
char buff[20+FN_REFLEN];
1518
uint32_t keynr,primary_key;
1519
snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1520
if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1522
fprintf(stderr, _("%s: Can't get keys for table %s\n"),
1523
internal::my_progname, result_table);
1529
/* Find first which key is primary key */
1531
primary_key=INT_MAX;
1532
while ((row= drizzle_row_next(&result)))
1534
if (atoi(row[3]) == 1)
1537
#ifdef FORCE_PRIMARY_KEY
1538
if (atoi(row[1]) == 0 && primary_key == INT_MAX)
1541
if (!strcmp(row[2],"PRIMARY"))
1548
drizzle_row_seek(&result,0);
1550
while ((row= drizzle_row_next(&result)))
1554
print_xml_row(sql_file, "key", &result, &row);
1558
if (atoi(row[3]) == 1)
1561
putc(')', sql_file);
1562
if (atoi(row[1])) /* Test if duplicate key */
1563
/* Duplicate allowed */
1564
fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0));
1565
else if (keynr == primary_key)
1566
fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
1568
fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
1572
putc(',', sql_file);
1573
fputs(quote_name(row[4], name_buff, 0), sql_file);
1575
fprintf(sql_file, " (%s)",row[7]); /* Sub key */
1578
drizzle_result_free(&result);
1582
putc(')', sql_file);
1583
fputs("\n)",sql_file);
1586
/* Get DRIZZLE specific create options */
1589
char show_name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+2+24];
1591
/* Check memory for quote_for_like() */
1592
snprintf(buff, sizeof(buff), "show table status like %s",
1593
quote_for_like(table, show_name_buff));
1595
if (!drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1597
if (!(row= drizzle_row_next(&result)))
1600
_("Error: Couldn't read status information for table %s\n"),
1606
print_xml_row(sql_file, "options", &result, &row);
1609
fputs("/*!",sql_file);
1610
print_value(sql_file,&result,row,"engine=","Engine",0);
1611
print_value(sql_file,&result,row,"","Create_options",0);
1612
print_value(sql_file,&result,row,"comment=","Comment",1);
1614
fputs(" */",sql_file);
1618
drizzle_result_free(&result);
1622
fputs(";\n", sql_file);
1624
fputs("\t</table_structure>\n", sql_file);
1628
if (complete_insert) {
1629
insert_pat.append(") VALUES ");
1630
if (!extended_insert)
1631
insert_pat.append("(");
1633
if (sql_file != md_result_file)
1635
fputs("\n", sql_file);
1636
write_footer(sql_file);
1640
} /* get_table_structure */
1642
static void add_load_option(string &str, const char *option,
1643
const char *option_value)
1647
/* Null value means we don't add this option. */
1653
if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
1655
/* It's a hex constant, don't escape */
1656
str.append(option_value);
1660
/* char constant; escape */
1661
field_escape(str, option_value);
1667
Allow the user to specify field terminator strings like:
1668
"'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
1669
This is done by doubling ' and add a end -\ if needed to avoid
1670
syntax errors from the SQL parser.
1673
static void field_escape(string &in, const char *from)
1675
uint32_t end_backslashes= 0;
1684
end_backslashes^=1; /* find odd number of backslashes */
1687
if (*from == '\'' && !end_backslashes)
1689
/* We want a duplicate of "'" for DRIZZLE */
1696
/* Add missing backslashes if user has specified odd number of backs.*/
1697
if (end_backslashes)
1710
dump_table saves database contents as a series of INSERT statements.
1721
static void dump_table(char *table, char *db)
1724
char table_buff[DRIZZLE_MAX_TABLE_SIZE+3];
1725
string query_string;
1726
char table_type[DRIZZLE_MAX_TABLE_SIZE];
1727
char *result_table, table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3], *opt_quoted_table;
1729
uint32_t rownr, row_break, total_length, init_length;
1730
uint64_t num_fields= 0;
1731
drizzle_return_t ret;
1732
drizzle_result_st result;
1733
drizzle_column_st *column;
1738
Make sure you get the create table info before the following check for
1739
--no-data flag below. Otherwise, the create table info won't be printed.
1741
if (!get_table_structure(table, db, table_type, &ignore_flag, &num_fields))
1743
maybe_die(EX_TABLE_STATUS, _("Error retrieving table structure for table: \"%s\""), table);
1747
/* Check --no-data flag */
1750
verbose_msg(_("-- Skipping dump data for table '%s', --no-data was used\n"),
1756
If the table type is a merge table or any type that has to be
1757
_completely_ ignored and no data dumped
1759
if (ignore_flag & IGNORE_DATA)
1761
verbose_msg(_("-- Warning: Skipping data for table '%s' because " \
1762
"it's of type %s\n"), table, table_type);
1765
/* Check that there are any fields in the table */
1766
if (num_fields == 0)
1768
verbose_msg(_("-- Skipping dump data for table '%s', it has no fields\n"),
1773
result_table= quote_name(table,table_buff, 1);
1774
opt_quoted_table= quote_name(table, table_buff2, 0);
1776
verbose_msg(_("-- Sending SELECT query...\n"));
1778
query_string.clear();
1779
query_string.reserve(1024);
1783
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
1786
Convert the path to native os format
1787
and resolve to the full filepath.
1789
internal::convert_dirname(tmp_path,path,NULL);
1790
internal::my_load_path(tmp_path, tmp_path, NULL);
1791
internal::fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
1793
/* Must delete the file that 'INTO OUTFILE' will write to */
1794
internal::my_delete(filename, MYF(0));
1796
/* now build the query string */
1798
query_string.append( "SELECT * INTO OUTFILE '");
1799
query_string.append( filename);
1800
query_string.append( "'");
1802
if (fields_terminated || enclosed || opt_enclosed || escaped)
1803
query_string.append( " FIELDS");
1805
add_load_option(query_string, " TERMINATED BY ", fields_terminated);
1806
add_load_option(query_string, " ENCLOSED BY ", enclosed);
1807
add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
1808
add_load_option(query_string, " ESCAPED BY ", escaped);
1809
add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
1811
query_string.append( " FROM ");
1812
query_string.append( result_table);
1816
query_string.append( " WHERE ");
1817
query_string.append( where);
1822
query_string.append( " ORDER BY ");
1823
query_string.append( order_by);
1826
if (drizzle_query(&dcon, &result, query_string.c_str(),
1827
query_string.length(), &ret) == NULL ||
1828
ret != DRIZZLE_RETURN_OK)
1830
DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
1834
drizzle_result_free(&result);
1838
if (!opt_xml && opt_comments)
1840
fprintf(md_result_file,_("\n--\n-- Dumping data for table %s\n--\n"),
1842
check_io(md_result_file);
1845
query_string.append( "SELECT * FROM ");
1846
query_string.append( result_table);
1850
if (!opt_xml && opt_comments)
1852
fprintf(md_result_file, "-- WHERE: %s\n", where);
1853
check_io(md_result_file);
1856
query_string.append( " WHERE ");
1857
query_string.append( where);
1861
if (!opt_xml && opt_comments)
1863
fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
1864
check_io(md_result_file);
1866
query_string.append( " ORDER BY ");
1867
query_string.append( order_by);
1870
if (!opt_xml && !opt_compact)
1872
fputs("\n", md_result_file);
1873
check_io(md_result_file);
1875
if (drizzleclient_query_with_error_report(&dcon, &result,
1876
query_string.c_str(), quick))
1881
verbose_msg(_("-- Retrieving rows...\n"));
1882
if (drizzle_result_column_count(&result) != num_fields)
1884
fprintf(stderr,_("%s: Error in field count for table: %s ! Aborting.\n"),
1885
internal::my_progname, result_table);
1886
error= EX_CONSCHECK;
1887
drizzle_result_free(&result);
1891
/* Moved disable keys to after lock per bug 15977 */
1892
if (opt_disable_keys)
1894
fprintf(md_result_file, "ALTER TABLE %s DISABLE KEYS;\n",
1896
check_io(md_result_file);
1899
total_length= DRIZZLE_MAX_LINE_LENGTH; /* Force row break */
1902
init_length=(uint32_t) insert_pat.length()+4;
1904
print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
1908
fprintf(md_result_file, "set autocommit=0;\n");
1909
check_io(md_result_file);
1922
drizzle_row_free(&result, row);
1924
row= drizzle_row_buffer(&result, &ret);
1925
if (ret != DRIZZLE_RETURN_OK)
1928
_("%s: Error reading rows for table: %s (%d:%s) ! Aborting.\n"),
1929
internal::my_progname, result_table, ret, drizzle_con_error(&dcon));
1930
drizzle_result_free(&result);
1935
row= drizzle_row_next(&result);
1940
lengths= drizzle_row_field_sizes(&result);
1943
if ((rownr % show_progress_size) == 0)
1945
verbose_msg(_("-- %"PRIu32" of ~%"PRIu64" rows dumped for table %s\n"), rownr, total_rows, opt_quoted_table);
1947
if (!extended_insert && !opt_xml)
1949
fputs(insert_pat.c_str(),md_result_file);
1950
check_io(md_result_file);
1952
drizzle_column_seek(&result,0);
1956
fputs("\t<row>\n", md_result_file);
1957
check_io(md_result_file);
1960
for (i= 0; i < drizzle_result_column_count(&result); i++)
1963
uint32_t length= lengths[i];
1965
if (!(column= drizzle_column_next(&result)))
1967
_("Not enough fields from table %s! Aborting.\n"),
1971
63 is my_charset_bin. If charsetnr is not 63,
1972
we have not a BLOB but a TEXT column.
1973
we'll dump in hex only BLOB columns.
1975
is_blob= (opt_hex_blob && drizzle_column_charset(column) == 63 &&
1976
(drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_VARCHAR ||
1977
drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_BLOB)) ? 1 : 0;
1978
if (extended_insert && !opt_xml)
1982
extended_row.clear();
1983
extended_row.append("(");
1986
extended_row.append(",");
1992
if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
1995
"length * 2 + 2" is OK for both HEX and non-HEX modes:
1996
- In HEX mode we need exactly 2 bytes per character
1997
plus 2 bytes for '0x' prefix.
1998
- In non-HEX mode we need up to 2 bytes per character,
1999
plus 2 bytes for leading and trailing '\'' characters.
2000
Also we need to reserve 1 byte for terminating '\0'.
2002
char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
2003
memset(tmp_str, '\0', length * 2 + 2 + 1);
2004
if (opt_hex_blob && is_blob)
2006
extended_row.append("0x");
2007
drizzle_hex_string(tmp_str, row[i], length);
2008
extended_row.append(tmp_str);
2012
extended_row.append("'");
2013
drizzle_escape_string(tmp_str, row[i],length);
2014
extended_row.append(tmp_str);
2015
extended_row.append("'");
2021
/* change any strings ("inf", "-inf", "nan") into NULL */
2023
if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
2024
my_isalpha(charset_info, ptr[1])))
2025
extended_row.append( "NULL");
2028
extended_row.append( ptr);
2033
extended_row.append("''");
2036
extended_row.append("NULL");
2042
fputc(',', md_result_file);
2043
check_io(md_result_file);
2047
if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
2051
if (opt_hex_blob && is_blob && length)
2053
/* Define xsi:type="xs:hexBinary" for hex encoded data */
2054
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2055
drizzle_column_name(column), "xsi:type=", "xs:hexBinary", NULL);
2056
print_blob_as_hex(md_result_file, row[i], length);
2060
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2061
drizzle_column_name(column), NULL);
2062
print_quoted_xml(md_result_file, row[i], length);
2064
fputs("</field>\n", md_result_file);
2066
else if (opt_hex_blob && is_blob && length)
2068
fputs("0x", md_result_file);
2069
print_blob_as_hex(md_result_file, row[i], length);
2072
unescape(md_result_file, row[i], length);
2076
/* change any strings ("inf", "-inf", "nan") into NULL */
2080
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2081
drizzle_column_name(column), NULL);
2082
fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
2084
fputs("</field>\n", md_result_file);
2086
else if (my_isalpha(charset_info, *ptr) ||
2087
(*ptr == '-' && my_isalpha(charset_info, ptr[1])))
2088
fputs("NULL", md_result_file);
2090
fputs(ptr, md_result_file);
2095
/* The field value is NULL */
2097
fputs("NULL", md_result_file);
2099
print_xml_null_tag(md_result_file, "\t\t", "field name=",
2100
drizzle_column_name(column), "\n");
2102
check_io(md_result_file);
2108
fputs("\t</row>\n", md_result_file);
2109
check_io(md_result_file);
2112
if (extended_insert)
2114
uint32_t row_length;
2115
extended_row.append(")");
2116
row_length= 2 + extended_row.length();
2117
if (total_length + row_length < DRIZZLE_MAX_LINE_LENGTH)
2119
total_length+= row_length;
2120
fputc(',',md_result_file); /* Always row break */
2121
fputs(extended_row.c_str(),md_result_file);
2126
fputs(";\n", md_result_file);
2127
row_break=1; /* This is first row */
2129
fputs(insert_pat.c_str(),md_result_file);
2130
fputs(extended_row.c_str(),md_result_file);
2131
total_length= row_length+init_length;
2133
check_io(md_result_file);
2137
fputs(");\n", md_result_file);
2138
check_io(md_result_file);
2142
/* XML - close table tag and supress regular output */
2144
fputs("\t</table_data>\n", md_result_file);
2145
else if (extended_insert && row_break)
2146
fputs(";\n", md_result_file); /* If not empty table */
2147
fflush(md_result_file);
2148
check_io(md_result_file);
2150
/* Moved enable keys to before unlock per bug 15977 */
2151
if (opt_disable_keys)
2153
fprintf(md_result_file,"ALTER TABLE %s ENABLE KEYS;\n",
2155
check_io(md_result_file);
2159
fprintf(md_result_file, "commit;\n");
2160
check_io(md_result_file);
2162
drizzle_result_free(&result);
2172
static char *getTableName(int reset)
2174
static drizzle_result_st result;
2175
static bool have_result= false;
2180
if (drizzleclient_query_with_error_report(&dcon, &result, "SHOW TABLES", false))
2185
if ((row= drizzle_row_next(&result)))
2189
drizzle_row_seek(&result, 0);
2192
drizzle_result_free(&result);
2196
} /* getTableName */
342
2199
static int dump_all_databases()
344
2201
drizzle_row_t row;
345
drizzle_result_st *tableres;
2202
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)))
2205
if (drizzleclient_query_with_error_report(&dcon, &tableres, "SHOW DATABASES", false))
2207
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);
2209
if (dump_all_tables_in_db(row[0]))
371
db_connection->freeResult(tableres);
2212
drizzle_result_free(&tableres);
374
2215
/* dump_all_databases */
377
static int dump_databases(const vector<string> &db_names)
2218
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)
2224
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);
2226
if (dump_all_tables_in_db(*db))
393
2230
} /* 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);
2234
Table Specific database initalization.
2238
qdatabase quoted name of the database
2245
int init_dumping_tables(char *qdatabase)
2251
drizzle_result_st result;
2252
drizzle_return_t ret;
2254
snprintf(qbuf, sizeof(qbuf),
2255
"SHOW CREATE DATABASE IF NOT EXISTS %s",
2258
if (drizzle_query_str(&dcon, &result, qbuf, &ret) == NULL ||
2259
ret != DRIZZLE_RETURN_OK)
2261
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2262
drizzle_result_free(&result);
2264
/* Old server version, dump generic CREATE DATABASE */
2265
if (opt_drop_database)
2266
fprintf(md_result_file,
2267
"\nDROP DATABASE IF EXISTS %s;\n",
2269
fprintf(md_result_file,
2270
"\nCREATE DATABASE IF NOT EXISTS %s;\n",
2275
if (drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
2277
if (opt_drop_database)
2278
fprintf(md_result_file,
2279
"\nDROP DATABASE IF EXISTS %s;\n",
2281
row = drizzle_row_next(&result);
2282
if (row != NULL && row[1])
2284
fprintf(md_result_file,"\n%s;\n",row[1]);
2287
drizzle_result_free(&result);
2291
} /* init_dumping_tables */
2294
static int init_dumping(char *database, int init_func(char*))
2296
drizzle_result_st result;
2297
drizzle_return_t ret;
2300
/* If this DB contains non-standard tables we don't want it */
2302
snprintf(qbuf, sizeof(qbuf), "SELECT TABLE_NAME FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='%s' AND TABLE_TYPE != 'STANDARD'", database);
2304
if (drizzle_query_str(&dcon, &result, qbuf, &ret) != NULL)
2306
drizzle_result_buffer(&result);
2307
if (drizzle_result_row_count(&result) > 0)
2309
drizzle_result_free(&result);
2314
drizzle_result_free(&result);
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
unordered_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,
2421
drizzled::memory::Root *root)
2424
drizzle_result_st result;
2426
char query[50 + 2*DRIZZLE_MAX_TABLE_SIZE];
2427
char show_name_buff[FN_REFLEN];
2431
/* Check memory for quote_for_like() */
2432
assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
2433
snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
2434
quote_for_like(old_table_name, show_name_buff));
2436
if (drizzleclient_query_with_error_report(&dcon, &result, query, false))
2439
num_rows= drizzle_result_row_count(&result);
2445
TODO-> Return all matching rows
2447
row= drizzle_row_next(&result);
2448
lengths= drizzle_row_field_sizes(&result);
2449
name= root->strmake_root(row[0], lengths[0]);
2451
drizzle_result_free(&result);
2457
static int dump_selected_tables(char *db, char **table_names, int tables)
2459
drizzled::memory::Root root;
2460
char **dump_tables, **pos, **end;
2461
drizzle_result_st result;
2462
drizzle_return_t ret;
2465
if (init_dumping(db, init_dumping_tables))
2468
root.init_alloc_root(8192);
2469
if (!(dump_tables= pos= (char**) root.alloc_root(tables * sizeof(char *))))
2470
die(EX_EOM, _("alloc_root failure."));
2472
for (; tables > 0 ; tables-- , table_names++)
2474
/* the table name passed on commandline may be wrong case */
2475
if ((*pos= get_actual_table_name(*table_names, &root)))
2483
root.free_root(MYF(0));
2485
maybe_die(EX_ILLEGAL_TABLE, _("Couldn't find table: \"%s\""), *table_names);
2486
/* We shall countinue here, if --force was given */
2493
if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
2494
ret != DRIZZLE_RETURN_OK)
2497
root.free_root(MYF(0));
2498
DB_error(&result, ret, _("when doing refresh"));
2499
/* We shall countinue here, if --force was given */
2502
drizzle_result_free(&result);
2505
print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NULL);
2507
/* Dump each selected table */
2508
for (pos= dump_tables; pos < end; pos++)
2509
dump_table(*pos, db);
2511
root.free_root(MYF(0));
2516
fputs("</database>\n", md_result_file);
2517
check_io(md_result_file);
414
2520
} /* dump_selected_tables */
416
static int do_flush_tables_read_lock()
2522
static int do_flush_tables_read_lock(drizzle_con_st *drizzle_con)
419
2525
We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
423
2529
and most client connections are stalled. Of course, if a second long
424
2530
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");
2533
( drizzleclient_query_with_error_report(drizzle_con, 0, "FLUSH TABLES", false) ||
2534
drizzleclient_query_with_error_report(drizzle_con, 0,
2535
"FLUSH TABLES WITH READ LOCK", false) );
2538
static int do_unlock_tables(drizzle_con_st *drizzle_con)
2540
return drizzleclient_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES", false);
2543
static int start_transaction(drizzle_con_st *drizzle_con)
2545
return (drizzleclient_query_with_error_report(drizzle_con, 0,
2546
"SET SESSION TRANSACTION ISOLATION "
2547
"LEVEL REPEATABLE READ", false) ||
2548
drizzleclient_query_with_error_report(drizzle_con, 0,
2549
"START TRANSACTION "
2550
"WITH CONSISTENT SNAPSHOT", false));
2554
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
2555
char **err_pos, uint32_t *err_len)
2557
const char *end= x + length;
2562
*err_pos= 0; /* No error yet */
2563
while (end > x && my_isspace(charset_info, end[-1]))
2569
const char *start= x;
2572
const char *pos= start;
2575
for (; pos != end && *pos != ','; pos++) ;
2576
var_len= (uint32_t) (pos - start);
2577
strncpy(buff, start, min((uint32_t)sizeof(buff), var_len+1));
2578
find= find_type(buff, lib, var_len);
2581
*err_pos= (char*) start;
2585
found|= (uint32_t)((int64_t) 1 << (find - 1));
2595
/* Print a value with a prefix on file */
2596
static void print_value(FILE *file, drizzle_result_st *result, drizzle_row_t row,
2597
const char *prefix, const char *name,
2600
drizzle_column_st *column;
2601
drizzle_column_seek(result, 0);
2603
for ( ; (column= drizzle_column_next(result)) ; row++)
2605
if (!strcmp(drizzle_column_name(column),name))
2607
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
2610
fputs(prefix, file);
2612
unescape(file,row[0],(uint32_t) strlen(row[0]));
2614
fputs(row[0], file);
2620
return; /* This shouldn't happen */
2624
* Fetches a row from a result based on a field name
2625
* Returns const char* of the data in that row or NULL if not found
2628
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row, const char *name)
2630
drizzle_column_st *column;
2631
drizzle_column_seek(result, 0);
2633
for ( ; (column= drizzle_column_next(result)) ; row++)
2635
if (!strcmp(drizzle_column_name(column),name))
2637
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
2639
drizzle_column_seek(result, 0);
2644
drizzle_column_seek(result, 0);
2652
Check if we the table is one of the table types that should be ignored:
2653
MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
2654
If the table should be altogether ignored, it returns a true, false if it
2655
should not be ignored. If the user has selected to use INSERT DELAYED, it
2656
sets the value of the bool pointer supports_delayed_inserts to 0 if not
2657
supported, 1 if it is supported.
2661
check_if_ignore_table()
2662
table_name Table name to check
2663
table_type Type of table
2666
drizzle Drizzle connection
2667
verbose Write warning messages
2670
char (bit value) See IGNORE_ values at top
2673
char check_if_ignore_table(const char *table_name, char *table_type)
2675
char result= IGNORE_NONE;
2676
char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
2677
const char *number_of_rows= NULL;
2678
drizzle_result_st res;
2681
/* Check memory for quote_for_like() */
2682
assert(2*sizeof(table_name) < sizeof(show_name_buff));
2683
snprintf(buff, sizeof(buff), "show table status like %s",
2684
quote_for_like(table_name, show_name_buff));
2685
if (drizzleclient_query_with_error_report(&dcon, &res, buff, false))
2689
if (!(row= drizzle_row_next(&res)))
2692
_("Error: Couldn't read status information for table %s\n"),
2694
drizzle_result_free(&res);
2695
return(result); /* assume table is ok */
2699
if ((number_of_rows= fetch_named_row(&res, row, "Rows")) != NULL)
2701
total_rows= strtoul(number_of_rows, NULL, 10);
2705
If the table type matches any of these, we do support delayed inserts.
2706
Note-> we do not want to skip dumping this table if if is not one of
2707
these types, but we do want to use delayed inserts in the dump if
2708
the table type is _NOT_ one of these types
2711
strncpy(table_type, row[1], DRIZZLE_MAX_TABLE_SIZE-1);
2714
if (strcmp(table_type,"MyISAM") &&
2715
strcmp(table_type,"ARCHIVE") &&
2716
strcmp(table_type,"HEAP") &&
2717
strcmp(table_type,"MEMORY"))
2718
result= IGNORE_INSERT_DELAYED;
2721
drizzle_result_free(&res);
2727
Get string of comma-separated primary key field names
2730
char *primary_key_fields(const char *table_name)
2731
RETURNS pointer to allocated buffer (must be freed by caller)
2732
table_name quoted table name
2735
Use SHOW KEYS FROM table_name, allocate a buffer to hold the
2736
field names, and then build that string and return the pointer
2739
Returns NULL if there is no PRIMARY or UNIQUE key on the table,
2740
or if there is some failure. It is better to continue to dump
2741
the table unsorted, rather than exit without dumping the data.
2744
static char *primary_key_fields(const char *table_name)
2746
drizzle_result_st res;
2747
drizzle_return_t ret;
2749
/* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
2750
char show_keys_buff[15 + DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
2751
uint32_t result_length= 0;
2753
char buff[DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
2756
snprintf(show_keys_buff, sizeof(show_keys_buff),
2757
"SHOW KEYS FROM %s", table_name);
2758
if (drizzle_query_str(&dcon, &res, show_keys_buff, &ret) == NULL ||
2759
ret != DRIZZLE_RETURN_OK)
2761
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2763
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2764
" records are NOT sorted (%s)\n"),
2765
table_name, drizzle_result_error(&res));
2766
drizzle_result_free(&res);
2770
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2771
" records are NOT sorted (%s)\n"),
2772
table_name, drizzle_con_error(&dcon));
2778
if (drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
2780
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2781
" records are NOT sorted (%s)\n"),
2782
table_name, drizzle_con_error(&dcon));
2787
* Figure out the length of the ORDER BY clause result.
2788
* Note that SHOW KEYS is ordered: a PRIMARY key is always the first
2789
* row, and UNIQUE keys come before others. So we only need to check
2790
* the first key, not all keys.
2792
if ((row= drizzle_row_next(&res)) && atoi(row[1]) == 0)
2797
quoted_field= quote_name(row[4], buff, 0);
2798
result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
2799
} while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1);
2802
/* Build the ORDER BY clause result */
2806
/* result (terminating \0 is already in result_length) */
2808
size_t result_length_alloc= result_length + 10;
2809
result= (char *)malloc(result_length_alloc);
2812
fprintf(stderr, _("Error: Not enough memory to store ORDER BY clause\n"));
2813
drizzle_result_free(&res);
2816
drizzle_row_seek(&res, 0);
2817
row= drizzle_row_next(&res);
2818
quoted_field= quote_name(row[4], buff, 0);
2819
end= strcpy(result, quoted_field) + strlen(quoted_field);
2820
result_length_alloc -= strlen(quoted_field);
2821
while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1)
2823
quoted_field= quote_name(row[4], buff, 0);
2824
end+= snprintf(end, result_length_alloc, ",%s",quoted_field);
2825
result_length_alloc -= strlen(quoted_field);
2829
drizzle_result_free(&res);
446
2834
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();
2837
MY_INIT("drizzledump");
2838
drizzle_result_st result;
2840
compatible_mode_normal_str[0]= 0;
2842
exit_code= get_options(&argc, &argv);
732
2845
free_resources();
733
2846
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())
2849
if (connect_to_db(current_host, current_user, opt_password))
2852
exit(EX_DRIZZLEERR);
2855
write_header(md_result_file, *argv);
2857
if ((opt_lock_all_tables) && do_flush_tables_read_lock(&dcon))
768
if (opt_single_transaction && start_transaction())
2859
if (opt_single_transaction && start_transaction(&dcon))
770
2861
if (opt_lock_all_tables)
771
db_connection->queryNoResult("FLUSH LOGS");
772
if (opt_single_transaction && do_unlock_tables()) /* unlock but no commit! */
2863
if (drizzleclient_query_with_error_report(&dcon, &result, "FLUSH LOGS", false))
2865
drizzle_result_free(&result);
2866
flush_logs= 0; /* not anymore; that would not be sensible */
2868
if (opt_single_transaction && do_unlock_tables(&dcon)) /* unlock but no commit! */
777
2873
dump_all_databases();
780
if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
2875
else if (argc > 1 && !opt_databases)
782
string database_used= *vm["database-used"].as< vector<string> >().begin();
783
2877
/* 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)
2878
dump_selected_tables(*argv, (argv + 1), (argc - 1));
2882
dump_databases(argv);
814
2885
/* ensure dumped data flushed */
815
2886
if (md_result_file && fflush(md_result_file))