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;
105
static bool tty_password= false;
72
106
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;
107
static bool opt_comments= false;
108
static bool opt_compact= false;
109
static bool opt_hex_blob= false;
110
static bool opt_order_by_primary=false;
111
static bool opt_ignore= false;
112
static bool opt_complete_insert= false;
113
static bool opt_drop_database= false;
114
static bool opt_replace_into= false;
115
static bool opt_routines= false;
116
static bool opt_alltspcs= 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;
86
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;
87
138
static uint32_t opt_drizzle_port= 0;
88
139
static int first_error= 0;
89
140
static string extended_row;
90
141
FILE *md_result_file= 0;
91
142
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);
144
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
146
static const char *compatible_mode_names[]=
148
"MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
149
"MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
153
static TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
154
"", compatible_mode_names, NULL};
156
unordered_set<string> ignore_table;
158
static struct option my_long_options[] =
160
{"all", 'a', "Deprecated. Use --create-options instead.",
161
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
163
{"all-databases", 'A',
164
"Dump all the databases. This will be same as --databases with all databases selected.",
165
(char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
167
{"all-tablespaces", 'Y',
168
"Dump all the tablespaces.",
169
(char**) &opt_alltspcs, (char**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
171
{"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
172
(char**) &opt_drop_database, (char**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
174
{"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
175
(char**) &opt_drop, (char**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
177
{"allow-keywords", OPT_KEYWORDS,
178
"Allow creation of column names that are keywords.", (char**) &opt_keywords,
179
(char**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
180
{"comments", 'i', "Write additional information.",
181
(char**) &opt_comments, (char**) &opt_comments, 0, GET_BOOL, NO_ARG,
183
{"compatible", OPT_COMPATIBLE,
184
"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.",
185
(char**) &opt_compatible_mode_str, (char**) &opt_compatible_mode_str, 0,
186
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
187
{"compact", OPT_COMPACT,
188
"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",
189
(char**) &opt_compact, (char**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
191
{"complete-insert", 'c', "Use complete insert statements.",
192
(char**) &opt_complete_insert, (char**) &opt_complete_insert, 0, GET_BOOL,
193
NO_ARG, 0, 0, 0, 0, 0, 0},
194
{"compress", 'C', "Use compression in server/client protocol.",
195
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
197
{"create-options", OPT_CREATE_OPTIONS,
198
"Include all DRIZZLE specific create options.",
199
(char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
202
"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.",
203
(char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
205
{"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
206
(char**) &opt_delayed, (char**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
208
{"disable-keys", 'K',
209
"'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will be put in the output.", (char**) &opt_disable_keys,
210
(char**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
211
{"extended-insert", 'e',
212
"Allows utilization of the new, much faster INSERT syntax.",
213
(char**) &extended_insert, (char**) &extended_insert, 0, GET_BOOL, NO_ARG,
215
{"fields-terminated-by", OPT_FTB,
216
"Fields in the textfile are terminated by ...", (char**) &fields_terminated,
217
(char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
218
{"fields-enclosed-by", OPT_ENC,
219
"Fields in the importfile are enclosed by ...", (char**) &enclosed,
220
(char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
221
{"fields-optionally-enclosed-by", OPT_O_ENC,
222
"Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
223
(char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
224
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
225
(char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
226
{"flush-logs", 'F', "Flush logs file in server before starting dump. "
227
"Note that if you dump many databases at once (using the option "
228
"--databases= or --all-databases), the logs will be flushed for "
229
"each database dumped. The exception is when using --lock-all-tables "
230
"in this case the logs will be flushed only once, corresponding "
231
"to the moment all tables are locked. So if you want your dump and "
232
"the log flush to happen at the same exact moment you should use "
233
"--lock-all-tables or --flush-logs",
234
(char**) &flush_logs, (char**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
236
{"force", 'f', "Continue even if we get an sql-error.",
237
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG,
239
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
240
NO_ARG, 0, 0, 0, 0, 0, 0},
241
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
242
"VARBINARY, BLOB) in hexadecimal format.",
243
(char**) &opt_hex_blob, (char**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
244
{"host", 'h', "Connect to host.", (char**) ¤t_host,
245
(char**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
246
{"ignore-table", OPT_IGNORE_TABLE,
247
"Do not dump the specified table. To specify more than one table to ignore, "
248
"use the directive multiple times, once for each table. Each table must "
249
"be specified with both database and table names, e.g. --ignore-table=database.table",
250
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
251
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
252
(char**) &opt_ignore, (char**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
254
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
255
(char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
256
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
257
{"lock-all-tables", 'x', "Locks all tables across all databases. This "
258
"is achieved by taking a global read lock for the duration of the whole "
259
"dump. Automatically turns --single-transaction and --lock-tables off.",
260
(char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
262
{"mysql", 'm', N_("Use MySQL Protocol."),
263
(char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
265
{"no-autocommit", OPT_AUTOCOMMIT,
266
"Wrap tables with autocommit/commit statements.",
267
(char**) &opt_autocommit, (char**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
269
{"no-create-db", 'n',
270
"'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.}.",
271
(char**) &opt_create_db, (char**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
273
{"no-create-info", 't', "Don't write table creation info.",
274
(char**) &opt_no_create_info, (char**) &opt_no_create_info, 0, GET_BOOL,
275
NO_ARG, 0, 0, 0, 0, 0, 0},
276
{"no-data", 'd', "No row information.", (char**) &opt_no_data,
277
(char**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
278
{"no-set-names", 'N',
279
"Deprecated. Use --skip-set-charset instead.",
280
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
281
{"opt", OPT_OPTIMIZE,
282
"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.",
283
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
284
{"order-by-primary", OPT_ORDER_BY_PRIMARY,
285
"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.",
286
(char**) &opt_order_by_primary, (char**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
288
"Password to use when connecting to server. If password is not given it's solicited on the tty.",
289
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
290
{"port", 'p', "Port number to use for connection.",
291
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
292
{"quick", 'q', "Don't buffer query, dump directly to stdout.",
293
(char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
294
{"quote-names",'Q', "Quote table and column names with backticks (`).",
295
(char**) &opt_quoted, (char**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
297
{"replace", OPT_DRIZZLE_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
298
(char**) &opt_replace_into, (char**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
301
"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).",
302
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
303
{"routines", 'R', "Dump stored routines (functions and procedures).",
304
(char**) &opt_routines, (char**) &opt_routines, 0, GET_BOOL,
305
NO_ARG, 0, 0, 0, 0, 0, 0},
306
{"single-transaction", OPT_TRANSACTION,
307
"Creates a consistent snapshot by dumping all tables in a single "
308
"transaction. Works ONLY for tables stored in storage engines which "
309
"support multiversioning (currently only InnoDB does); the dump is NOT "
310
"guaranteed to be consistent for other storage engines. "
311
"While a --single-transaction dump is in process, to ensure a valid "
312
"dump file (correct table contents), no other "
313
"connection should use the following statements: ALTER TABLE, DROP "
314
"TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
315
"isolated from them. Option automatically turns off --lock-tables.",
316
(char**) &opt_single_transaction, (char**) &opt_single_transaction, 0,
317
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
318
{"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
319
(char**) &opt_dump_date, (char**) &opt_dump_date, 0,
320
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
321
{"skip-opt", OPT_SKIP_OPTIMIZATION,
322
"Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
323
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
325
"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.",
326
(char**) &path, (char**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
327
{"tables", OPT_TABLES, "Overrides option --databases (-B).",
328
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
329
{"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of rows before each output progress report (requires --verbose)."),
330
(char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
331
10000, 0, 0, 0, 0, 0},
332
{"user", 'u', "User for login if not current user.",
333
(char**) ¤t_user, (char**) ¤t_user, 0, GET_STR, REQUIRED_ARG,
335
{"verbose", 'v', "Print info about the various stages.",
336
(char**) &verbose, (char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
337
{"version",'V', "Output version information and exit.", 0, 0, 0,
338
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
339
{"where", 'w', "Dump only selected records; QUOTES mandatory!",
340
(char**) &where, (char**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
341
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
342
NO_ARG, 0, 0, 0, 0, 0, 0},
343
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
346
static const char *load_default_groups[]= { "drizzledump","client",0 };
348
static void maybe_exit(int error);
124
349
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);
350
static void maybe_die(int error, const char* reason, ...);
351
static void write_header(FILE *sql_file, char *db_name);
352
static void print_value(FILE *file, drizzle_result_st *result,
353
drizzle_row_t row, const char *prefix, const char *name,
355
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row,
357
static int dump_selected_tables(char *db, char **table_names, int tables);
358
static int dump_all_tables_in_db(char *db);
359
static int init_dumping_tables(char *);
360
static int init_dumping(char *, int init_func(char*));
361
static int dump_databases(char **);
128
362
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;
363
static char *quote_name(const char *name, char *buff, bool force);
364
char check_if_ignore_table(const char *table_name, char *table_type);
365
static char *primary_key_fields(const char *table_name);
368
Print the supplied message if in verbose mode
373
... variable number of parameters
375
static void verbose_msg(const char *fmt, ...)
384
vfprintf(stderr, fmt, args);
312
755
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
315
fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
758
fprintf(stderr, "%s: %s\n", internal::my_progname, buffer);
318
761
ignore_errors= 0; /* force the exit */
319
762
maybe_exit(error_num);
767
Prints out an error message and maybe kills the process.
771
error_num - process return value
772
fmt_reason - a format string for use by vsnprintf.
773
... - variable arguments for above fmt_reason string
776
This call prints out the formatted error message to stderr and then
777
terminates the process, unless the --force command line option is used.
779
This call should be used for non-fatal errors (such as database
780
errors) that the code may still be able to continue to the next unit
784
static void maybe_die(int error_num, const char* fmt_reason, ...)
788
va_start(args,fmt_reason);
789
vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
792
fprintf(stderr, "%s: %s\n", internal::my_progname, buffer);
795
maybe_exit(error_num);
801
Sends a query to server, optionally reads result, prints error message if
805
drizzleclient_query_with_error_report()
806
drizzle_con connection to use
807
res if non zero, result will be put there with
808
drizzleclient_store_result()
809
query query to send to server
812
0 query sending and (if res!=0) result reading went ok
816
static int drizzleclient_query_with_error_report(drizzle_con_st *con,
817
drizzle_result_st *result,
818
const char *query_str,
821
drizzle_return_t ret;
823
if (drizzle_query_str(con, result, query_str, &ret) == NULL ||
824
ret != DRIZZLE_RETURN_OK)
826
if (ret == DRIZZLE_RETURN_ERROR_CODE)
828
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
829
query_str, drizzle_result_error(result),
830
drizzle_result_error_code(result));
831
drizzle_result_free(result);
835
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
836
query_str, drizzle_con_error(con), ret);
842
ret= drizzle_column_buffer(result);
844
ret= drizzle_result_buffer(result);
845
if (ret != DRIZZLE_RETURN_OK)
847
drizzle_result_free(result);
848
maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
849
query_str, drizzle_con_error(con), ret);
857
Open a new .sql file to dump the table or view into
860
open_sql_file_for_table
861
name name of the table or view
864
0 Failed to open file
865
> 0 Handle of the open file
867
static FILE* open_sql_file_for_table(const char* table)
870
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
871
internal::convert_dirname(tmp_path,path,NULL);
872
res= fopen(internal::fn_format(filename, table, tmp_path, ".sql", 4), "w");
322
878
static void free_resources(void)
324
880
if (md_result_file && md_result_file != stdout)
325
881
fclose(md_result_file);
326
opt_password.erase();
884
internal::free_defaults(defaults_argv);
330
void maybe_exit(int error)
889
static void maybe_exit(int error)
332
891
if (!first_error)
333
892
first_error= error;
334
893
if (ignore_errors)
336
delete db_connection;
337
delete destination_connection;
895
drizzle_con_free(&dcon);
896
drizzle_free(&drizzle);
338
897
free_resources();
903
db_connect -- connects to the host and selects DB.
906
static int connect_to_db(char *host, char *user,char *passwd)
908
drizzle_return_t ret;
910
verbose_msg(_("-- Connecting to %s...\n"), host ? host : "localhost");
911
drizzle_create(&drizzle);
912
drizzle_con_create(&drizzle, &dcon);
913
drizzle_con_set_tcp(&dcon, host, opt_drizzle_port);
914
drizzle_con_set_auth(&dcon, user, passwd);
916
drizzle_con_add_options(&dcon, DRIZZLE_CON_MYSQL);
917
ret= drizzle_con_connect(&dcon);
918
if (ret != DRIZZLE_RETURN_OK)
920
DB_error(NULL, ret, "when trying to connect");
925
} /* connect_to_db */
929
** dbDisconnect -- disconnects from the host.
931
static void dbDisconnect(char *host)
933
verbose_msg(_("-- Disconnecting from %s...\n"), host ? host : "localhost");
934
drizzle_con_free(&dcon);
935
drizzle_free(&drizzle);
939
static void unescape(FILE *file,char *pos,uint32_t length)
943
if (!(tmp=(char*) malloc(length*2+1)))
944
die(EX_DRIZZLEERR, _("Couldn't allocate memory"));
946
drizzle_escape_string(tmp, pos, length);
956
static bool test_if_special_chars(const char *str)
958
for ( ; *str ; str++)
959
if (!my_isvar(charset_info,*str) && *str != '$')
962
} /* test_if_special_chars */
967
quote_name(name, buff, force)
969
Quotes char string, taking into account compatible mode
973
name Unquoted string containing that which will be quoted
974
buff The buffer that contains the quoted value, also returned
975
force Flag to make it ignore 'test_if_special_chars'
982
static char *quote_name(const char *name, char *buff, bool force)
987
if (!force && !opt_quoted && !test_if_special_chars(name))
1003
Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
1007
name name of the table
1008
buff quoted name of the table
1011
Quote \, _, ' and % characters
1013
Note: Because DRIZZLE uses the C escape syntax in strings
1014
(for example, '\n' to represent newline), you must double
1015
any '\' that you use in your LIKE strings. For example, to
1016
search for '\n', specify it as '\\n'. To search for '\', specify
1017
it as '\\\\' (the backslashes are stripped once by the parser
1018
and another time when the pattern match is done, leaving a
1019
single backslash to be matched).
1021
Example: "t\1" => "t\\\\1"
1024
static char *quote_for_like(const char *name, char *buff)
1036
else if (*name == '\'' || *name == '_' || *name == '%')
1047
Quote and print a string.
1051
xml_file - output file
1052
str - string to print
1056
Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1059
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
1063
for (end= str + len; str != end; str++)
1067
fputs("<", xml_file);
1070
fputs(">", xml_file);
1073
fputs("&", xml_file);
1076
fputs(""", xml_file);
1079
fputc(*str, xml_file);
1088
Print xml tag. Optionally add attribute(s).
1091
print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
1092
..., attribute_name_n, attribute_value_n, NULL)
1093
xml_file - output file
1094
sbeg - line beginning
1095
line_end - line ending
1096
tag_name - XML tag name.
1097
first_attribute_name - tag and first attribute
1098
first_attribute_value - (Implied) value of first attribute
1099
attribute_name_n - attribute n
1100
attribute_value_n - value of attribute n
1103
Print XML tag with any number of attribute="value" pairs to the xml_file.
1106
sbeg<tag_name first_attribute_name="first_attribute_value" ...
1107
attribute_name_n="attribute_value_n">send
1109
Additional arguments must be present in attribute/value pairs.
1110
The last argument should be the null character pointer.
1111
All attribute_value arguments MUST be NULL terminated strings.
1112
All attribute_value arguments will be quoted before output.
1115
static void print_xml_tag(FILE * xml_file, const char* sbeg,
1116
const char* line_end,
1117
const char* tag_name,
1118
const char* first_attribute_name, ...)
1121
const char *attribute_name, *attribute_value;
1123
fputs(sbeg, xml_file);
1124
fputc('<', xml_file);
1125
fputs(tag_name, xml_file);
1127
va_start(arg_list, first_attribute_name);
1128
attribute_name= first_attribute_name;
1129
while (attribute_name != NULL)
1131
attribute_value= va_arg(arg_list, char *);
1132
assert(attribute_value != NULL);
1134
fputc(' ', xml_file);
1135
fputs(attribute_name, xml_file);
1136
fputc('\"', xml_file);
1138
print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
1139
fputc('\"', xml_file);
1141
attribute_name= va_arg(arg_list, char *);
1145
fputc('>', xml_file);
1146
fputs(line_end, xml_file);
1152
Print xml tag with for a field that is null
1155
print_xml_null_tag()
1156
xml_file - output file
1157
sbeg - line beginning
1158
stag_atr - tag and attribute
1159
sval - value of attribute
1160
line_end - line ending
1163
Print tag with one attribute to the xml_file. Format is:
1164
<stag_atr="sval" xsi:nil="true"/>
1166
sval MUST be a NULL terminated string.
1167
sval string will be qouted before output.
1170
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
1171
const char* stag_atr, const char* sval,
1172
const char* line_end)
1174
fputs(sbeg, xml_file);
1175
fputs("<", xml_file);
1176
fputs(stag_atr, xml_file);
1177
fputs("\"", xml_file);
1178
print_quoted_xml(xml_file, sval, strlen(sval));
1179
fputs("\" xsi:nil=\"true\" />", xml_file);
1180
fputs(line_end, xml_file);
1186
Print xml tag with many attributes.
1190
xml_file - output file
1191
row_name - xml tag name
1192
tableRes - query result
1196
Print tag with many attribute to the xml_file. Format is:
1197
\t\t<row_name Atr1="Val1" Atr2="Val2"... />
1199
All atributes and values will be quoted before output.
1202
static void print_xml_row(FILE *xml_file, const char *row_name,
1203
drizzle_result_st *tableRes, drizzle_row_t *row)
1206
drizzle_column_st *column;
1207
size_t *lengths= drizzle_row_field_sizes(tableRes);
1209
fprintf(xml_file, "\t\t<%s", row_name);
1211
drizzle_column_seek(tableRes, 0);
1212
for (i= 0; (column= drizzle_column_next(tableRes)); i++)
1216
fputc(' ', xml_file);
1217
print_quoted_xml(xml_file, drizzle_column_name(column),
1218
strlen(drizzle_column_name(column)));
1219
fputs("=\"", xml_file);
1220
print_quoted_xml(xml_file, (*row)[i], lengths[i]);
1221
fputc('"', xml_file);
1225
fputs(" />\n", xml_file);
1231
Print hex value for blob data.
1235
output_file - output file
1236
str - string to print
1240
Print hex value for blob data.
1243
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
1245
/* sakaik got the idea to to provide blob's in hex notation. */
1246
const char *ptr= str, *end= ptr + len;
1247
for (; ptr < end ; ptr++)
1248
fprintf(output_file, "%02X", *((unsigned char *)ptr));
1249
check_io(output_file);
1253
get_table_structure -- retrievs database structure, prints out corresponding
1254
CREATE statement and fills out insert_pat if the table is the type we will
1260
table_type - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
1261
ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1262
num_fields - number of fields in the table
1265
true if success, false if error
1268
static bool get_table_structure(char *table, char *db, char *table_type,
1269
char *ignore_flag, uint64_t *num_fields)
1271
bool init=0, delayed, write_data, complete_insert;
1272
char *result_table, *opt_quoted_table;
1273
const char *insert_option;
1274
char name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE+3];
1275
char table_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+3];
1276
char table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3];
1277
char query_buff[QUERY_LENGTH];
1278
FILE *sql_file= md_result_file;
1279
drizzle_result_st result;
1282
*ignore_flag= check_if_ignore_table(table, table_type);
1284
delayed= opt_delayed;
1285
if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
1288
verbose_msg(_("-- Warning: Unable to use delayed inserts for table '%s' "
1289
"because it's of type %s\n"), table, table_type);
1293
if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1295
complete_insert= opt_complete_insert;
1299
insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
1300
delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
1302
verbose_msg(_("-- Retrieving table structure for table %s...\n"), table);
1304
result_table= quote_name(table, table_buff, 1);
1305
opt_quoted_table= quote_name(table, table_buff2, 0);
1307
if (opt_order_by_primary)
1310
order_by= primary_key_fields(result_table);
1315
/* using SHOW CREATE statement */
1316
if (!opt_no_create_info)
1318
/* Make an sql-file, if path was given iow. option -T was given */
1319
char buff[20+FN_REFLEN];
1320
const drizzle_column_st *column;
1322
snprintf(buff, sizeof(buff), "show create table %s", result_table);
1324
if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1329
if (!(sql_file= open_sql_file_for_table(table)))
1331
drizzle_result_free(&result);
1335
write_header(sql_file, db);
1337
if (!opt_xml && opt_comments)
1339
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1346
Even if the "table" is a view, we do a DROP TABLE here.
1348
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
1352
column= drizzle_column_index(&result, 0);
1354
row= drizzle_row_next(&result);
1356
fprintf(sql_file, "%s;\n", row[1]);
1359
drizzle_result_free(&result);
1362
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1365
if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
1373
If write_data is true, then we build up insert statements for
1374
the table's data. Note: in subsequent lines of code, this test
1375
will have to be performed each time we are appending to
1380
if (opt_replace_into)
1381
insert_pat.append("REPLACE ");
1383
insert_pat.append("INSERT ");
1384
insert_pat.append(insert_option);
1385
insert_pat.append("INTO ");
1386
insert_pat.append(opt_quoted_table);
1387
if (complete_insert)
1389
insert_pat.append(" (");
1393
insert_pat.append(" VALUES ");
1394
if (!extended_insert)
1395
insert_pat.append("(");
1399
while ((row= drizzle_row_next(&result)))
1401
if (complete_insert)
1405
insert_pat.append(", ");
1408
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1411
*num_fields= drizzle_result_row_count(&result);
1412
drizzle_result_free(&result);
1416
verbose_msg(_("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n"),
1417
internal::my_progname, drizzle_con_error(&dcon));
1419
snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1421
if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
1424
/* Make an sql-file, if path was given iow. option -T was given */
1425
if (!opt_no_create_info)
1429
if (!(sql_file= open_sql_file_for_table(table)))
1431
drizzle_result_free(&result);
1434
write_header(sql_file, db);
1436
if (!opt_xml && opt_comments)
1437
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1440
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1442
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
1444
print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
1451
if (opt_replace_into)
1452
insert_pat.append("REPLACE ");
1454
insert_pat.append("INSERT ");
1455
insert_pat.append(insert_option);
1456
insert_pat.append("INTO ");
1457
insert_pat.append(result_table);
1458
if (complete_insert)
1459
insert_pat.append(" (");
1462
insert_pat.append(" VALUES ");
1463
if (!extended_insert)
1464
insert_pat.append("(");
1468
while ((row= drizzle_row_next(&result)))
1470
size_t *lengths= drizzle_row_field_sizes(&result);
1473
if (!opt_xml && !opt_no_create_info)
1475
fputs(",\n",sql_file);
1478
if (complete_insert)
1479
insert_pat.append(", ");
1482
if (complete_insert)
1483
insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1484
if (!opt_no_create_info)
1488
print_xml_row(sql_file, "field", &result, &row);
1493
fprintf(sql_file, " %s.%s %s", result_table,
1494
quote_name(row[SHOW_FIELDNAME],name_buff, 0),
1497
fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],
1500
if (row[SHOW_DEFAULT])
1502
fputs(" DEFAULT ", sql_file);
1503
unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1505
if (!row[SHOW_NULL][0])
1506
fputs(" NOT NULL", sql_file);
1507
if (row[SHOW_EXTRA][0])
1508
fprintf(sql_file, " %s",row[SHOW_EXTRA]);
1512
*num_fields= drizzle_result_row_count(&result);
1513
drizzle_result_free(&result);
1515
if (!opt_no_create_info)
1517
/* Make an sql-file, if path was given iow. option -T was given */
1518
char buff[20+FN_REFLEN];
1519
uint32_t keynr,primary_key;
1520
snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1521
if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1523
fprintf(stderr, _("%s: Can't get keys for table %s\n"),
1524
internal::my_progname, result_table);
1530
/* Find first which key is primary key */
1532
primary_key=INT_MAX;
1533
while ((row= drizzle_row_next(&result)))
1535
if (atoi(row[3]) == 1)
1538
#ifdef FORCE_PRIMARY_KEY
1539
if (atoi(row[1]) == 0 && primary_key == INT_MAX)
1542
if (!strcmp(row[2],"PRIMARY"))
1549
drizzle_row_seek(&result,0);
1551
while ((row= drizzle_row_next(&result)))
1555
print_xml_row(sql_file, "key", &result, &row);
1559
if (atoi(row[3]) == 1)
1562
putc(')', sql_file);
1563
if (atoi(row[1])) /* Test if duplicate key */
1564
/* Duplicate allowed */
1565
fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0));
1566
else if (keynr == primary_key)
1567
fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
1569
fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
1573
putc(',', sql_file);
1574
fputs(quote_name(row[4], name_buff, 0), sql_file);
1576
fprintf(sql_file, " (%s)",row[7]); /* Sub key */
1579
drizzle_result_free(&result);
1583
putc(')', sql_file);
1584
fputs("\n)",sql_file);
1587
/* Get DRIZZLE specific create options */
1590
char show_name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+2+24];
1592
/* Check memory for quote_for_like() */
1593
snprintf(buff, sizeof(buff), "show table status like %s",
1594
quote_for_like(table, show_name_buff));
1596
if (!drizzleclient_query_with_error_report(&dcon, &result, buff, false))
1598
if (!(row= drizzle_row_next(&result)))
1601
_("Error: Couldn't read status information for table %s\n"),
1607
print_xml_row(sql_file, "options", &result, &row);
1610
fputs("/*!",sql_file);
1611
print_value(sql_file,&result,row,"engine=","Engine",0);
1612
print_value(sql_file,&result,row,"","Create_options",0);
1613
print_value(sql_file,&result,row,"comment=","Comment",1);
1615
fputs(" */",sql_file);
1619
drizzle_result_free(&result);
1623
fputs(";\n", sql_file);
1625
fputs("\t</table_structure>\n", sql_file);
1629
if (complete_insert) {
1630
insert_pat.append(") VALUES ");
1631
if (!extended_insert)
1632
insert_pat.append("(");
1634
if (sql_file != md_result_file)
1636
fputs("\n", sql_file);
1637
write_footer(sql_file);
1641
} /* get_table_structure */
1643
static void add_load_option(string &str, const char *option,
1644
const char *option_value)
1648
/* Null value means we don't add this option. */
1654
if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
1656
/* It's a hex constant, don't escape */
1657
str.append(option_value);
1661
/* char constant; escape */
1662
field_escape(str, option_value);
1668
Allow the user to specify field terminator strings like:
1669
"'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
1670
This is done by doubling ' and add a end -\ if needed to avoid
1671
syntax errors from the SQL parser.
1674
static void field_escape(string &in, const char *from)
1676
uint32_t end_backslashes= 0;
1685
end_backslashes^=1; /* find odd number of backslashes */
1688
if (*from == '\'' && !end_backslashes)
1690
/* We want a duplicate of "'" for DRIZZLE */
1697
/* Add missing backslashes if user has specified odd number of backs.*/
1698
if (end_backslashes)
1711
dump_table saves database contents as a series of INSERT statements.
1722
static void dump_table(char *table, char *db)
1725
char table_buff[DRIZZLE_MAX_TABLE_SIZE+3];
1726
string query_string;
1727
char table_type[DRIZZLE_MAX_TABLE_SIZE];
1728
char *result_table, table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3], *opt_quoted_table;
1730
uint32_t rownr, row_break, total_length, init_length;
1731
uint64_t num_fields= 0;
1732
drizzle_return_t ret;
1733
drizzle_result_st result;
1734
drizzle_column_st *column;
1739
Make sure you get the create table info before the following check for
1740
--no-data flag below. Otherwise, the create table info won't be printed.
1742
if (!get_table_structure(table, db, table_type, &ignore_flag, &num_fields))
1744
maybe_die(EX_TABLE_STATUS, _("Error retrieving table structure for table: \"%s\""), table);
1748
/* Check --no-data flag */
1751
verbose_msg(_("-- Skipping dump data for table '%s', --no-data was used\n"),
1757
If the table type is a merge table or any type that has to be
1758
_completely_ ignored and no data dumped
1760
if (ignore_flag & IGNORE_DATA)
1762
verbose_msg(_("-- Warning: Skipping data for table '%s' because " \
1763
"it's of type %s\n"), table, table_type);
1766
/* Check that there are any fields in the table */
1767
if (num_fields == 0)
1769
verbose_msg(_("-- Skipping dump data for table '%s', it has no fields\n"),
1774
result_table= quote_name(table,table_buff, 1);
1775
opt_quoted_table= quote_name(table, table_buff2, 0);
1777
verbose_msg(_("-- Sending SELECT query...\n"));
1779
query_string.clear();
1780
query_string.reserve(1024);
1784
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
1787
Convert the path to native os format
1788
and resolve to the full filepath.
1790
internal::convert_dirname(tmp_path,path,NULL);
1791
internal::my_load_path(tmp_path, tmp_path, NULL);
1792
internal::fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
1794
/* Must delete the file that 'INTO OUTFILE' will write to */
1795
internal::my_delete(filename, MYF(0));
1797
/* now build the query string */
1799
query_string.append( "SELECT * INTO OUTFILE '");
1800
query_string.append( filename);
1801
query_string.append( "'");
1803
if (fields_terminated || enclosed || opt_enclosed || escaped)
1804
query_string.append( " FIELDS");
1806
add_load_option(query_string, " TERMINATED BY ", fields_terminated);
1807
add_load_option(query_string, " ENCLOSED BY ", enclosed);
1808
add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
1809
add_load_option(query_string, " ESCAPED BY ", escaped);
1810
add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
1812
query_string.append( " FROM ");
1813
query_string.append( result_table);
1817
query_string.append( " WHERE ");
1818
query_string.append( where);
1823
query_string.append( " ORDER BY ");
1824
query_string.append( order_by);
1827
if (drizzle_query(&dcon, &result, query_string.c_str(),
1828
query_string.length(), &ret) == NULL ||
1829
ret != DRIZZLE_RETURN_OK)
1831
DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
1835
drizzle_result_free(&result);
1839
if (!opt_xml && opt_comments)
1841
fprintf(md_result_file,_("\n--\n-- Dumping data for table %s\n--\n"),
1843
check_io(md_result_file);
1846
query_string.append( "SELECT * FROM ");
1847
query_string.append( result_table);
1851
if (!opt_xml && opt_comments)
1853
fprintf(md_result_file, "-- WHERE: %s\n", where);
1854
check_io(md_result_file);
1857
query_string.append( " WHERE ");
1858
query_string.append( where);
1862
if (!opt_xml && opt_comments)
1864
fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
1865
check_io(md_result_file);
1867
query_string.append( " ORDER BY ");
1868
query_string.append( order_by);
1871
if (!opt_xml && !opt_compact)
1873
fputs("\n", md_result_file);
1874
check_io(md_result_file);
1876
if (drizzleclient_query_with_error_report(&dcon, &result,
1877
query_string.c_str(), quick))
1882
verbose_msg(_("-- Retrieving rows...\n"));
1883
if (drizzle_result_column_count(&result) != num_fields)
1885
fprintf(stderr,_("%s: Error in field count for table: %s ! Aborting.\n"),
1886
internal::my_progname, result_table);
1887
error= EX_CONSCHECK;
1888
drizzle_result_free(&result);
1892
/* Moved disable keys to after lock per bug 15977 */
1893
if (opt_disable_keys)
1895
fprintf(md_result_file, "ALTER TABLE %s DISABLE KEYS;\n",
1897
check_io(md_result_file);
1900
total_length= DRIZZLE_MAX_LINE_LENGTH; /* Force row break */
1903
init_length=(uint32_t) insert_pat.length()+4;
1905
print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
1909
fprintf(md_result_file, "set autocommit=0;\n");
1910
check_io(md_result_file);
1923
drizzle_row_free(&result, row);
1925
row= drizzle_row_buffer(&result, &ret);
1926
if (ret != DRIZZLE_RETURN_OK)
1929
_("%s: Error reading rows for table: %s (%d:%s) ! Aborting.\n"),
1930
internal::my_progname, result_table, ret, drizzle_con_error(&dcon));
1931
drizzle_result_free(&result);
1936
row= drizzle_row_next(&result);
1941
lengths= drizzle_row_field_sizes(&result);
1944
if ((rownr % show_progress_size) == 0)
1946
verbose_msg(_("-- %"PRIu32" of ~%"PRIu64" rows dumped for table %s\n"), rownr, total_rows, opt_quoted_table);
1948
if (!extended_insert && !opt_xml)
1950
fputs(insert_pat.c_str(),md_result_file);
1951
check_io(md_result_file);
1953
drizzle_column_seek(&result,0);
1957
fputs("\t<row>\n", md_result_file);
1958
check_io(md_result_file);
1961
for (i= 0; i < drizzle_result_column_count(&result); i++)
1964
uint32_t length= lengths[i];
1966
if (!(column= drizzle_column_next(&result)))
1968
_("Not enough fields from table %s! Aborting.\n"),
1972
63 is my_charset_bin. If charsetnr is not 63,
1973
we have not a BLOB but a TEXT column.
1974
we'll dump in hex only BLOB columns.
1976
is_blob= (opt_hex_blob && drizzle_column_charset(column) == 63 &&
1977
(drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_VARCHAR ||
1978
drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_BLOB)) ? 1 : 0;
1979
if (extended_insert && !opt_xml)
1983
extended_row.clear();
1984
extended_row.append("(");
1987
extended_row.append(",");
1993
if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
1996
"length * 2 + 2" is OK for both HEX and non-HEX modes:
1997
- In HEX mode we need exactly 2 bytes per character
1998
plus 2 bytes for '0x' prefix.
1999
- In non-HEX mode we need up to 2 bytes per character,
2000
plus 2 bytes for leading and trailing '\'' characters.
2001
Also we need to reserve 1 byte for terminating '\0'.
2003
char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
2004
memset(tmp_str, '\0', length * 2 + 2 + 1);
2005
if (opt_hex_blob && is_blob)
2007
extended_row.append("0x");
2008
drizzle_hex_string(tmp_str, row[i], length);
2009
extended_row.append(tmp_str);
2013
extended_row.append("'");
2014
drizzle_escape_string(tmp_str, row[i],length);
2015
extended_row.append(tmp_str);
2016
extended_row.append("'");
2022
/* change any strings ("inf", "-inf", "nan") into NULL */
2024
if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
2025
my_isalpha(charset_info, ptr[1])))
2026
extended_row.append( "NULL");
2029
extended_row.append( ptr);
2034
extended_row.append("''");
2037
extended_row.append("NULL");
2043
fputc(',', md_result_file);
2044
check_io(md_result_file);
2048
if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
2052
if (opt_hex_blob && is_blob && length)
2054
/* Define xsi:type="xs:hexBinary" for hex encoded data */
2055
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2056
drizzle_column_name(column), "xsi:type=", "xs:hexBinary", NULL);
2057
print_blob_as_hex(md_result_file, row[i], length);
2061
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2062
drizzle_column_name(column), NULL);
2063
print_quoted_xml(md_result_file, row[i], length);
2065
fputs("</field>\n", md_result_file);
2067
else if (opt_hex_blob && is_blob && length)
2069
fputs("0x", md_result_file);
2070
print_blob_as_hex(md_result_file, row[i], length);
2073
unescape(md_result_file, row[i], length);
2077
/* change any strings ("inf", "-inf", "nan") into NULL */
2081
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
2082
drizzle_column_name(column), NULL);
2083
fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
2085
fputs("</field>\n", md_result_file);
2087
else if (my_isalpha(charset_info, *ptr) ||
2088
(*ptr == '-' && my_isalpha(charset_info, ptr[1])))
2089
fputs("NULL", md_result_file);
2091
fputs(ptr, md_result_file);
2096
/* The field value is NULL */
2098
fputs("NULL", md_result_file);
2100
print_xml_null_tag(md_result_file, "\t\t", "field name=",
2101
drizzle_column_name(column), "\n");
2103
check_io(md_result_file);
2109
fputs("\t</row>\n", md_result_file);
2110
check_io(md_result_file);
2113
if (extended_insert)
2115
uint32_t row_length;
2116
extended_row.append(")");
2117
row_length= 2 + extended_row.length();
2118
if (total_length + row_length < DRIZZLE_MAX_LINE_LENGTH)
2120
total_length+= row_length;
2121
fputc(',',md_result_file); /* Always row break */
2122
fputs(extended_row.c_str(),md_result_file);
2127
fputs(";\n", md_result_file);
2128
row_break=1; /* This is first row */
2130
fputs(insert_pat.c_str(),md_result_file);
2131
fputs(extended_row.c_str(),md_result_file);
2132
total_length= row_length+init_length;
2134
check_io(md_result_file);
2138
fputs(");\n", md_result_file);
2139
check_io(md_result_file);
2143
/* XML - close table tag and supress regular output */
2145
fputs("\t</table_data>\n", md_result_file);
2146
else if (extended_insert && row_break)
2147
fputs(";\n", md_result_file); /* If not empty table */
2148
fflush(md_result_file);
2149
check_io(md_result_file);
2151
/* Moved enable keys to before unlock per bug 15977 */
2152
if (opt_disable_keys)
2154
fprintf(md_result_file,"ALTER TABLE %s ENABLE KEYS;\n",
2156
check_io(md_result_file);
2160
fprintf(md_result_file, "commit;\n");
2161
check_io(md_result_file);
2163
drizzle_result_free(&result);
2173
static char *getTableName(int reset)
2175
static drizzle_result_st result;
2176
static bool have_result= false;
2181
if (drizzleclient_query_with_error_report(&dcon, &result, "SHOW TABLES", false))
2186
if ((row= drizzle_row_next(&result)))
2190
drizzle_row_seek(&result, 0);
2193
drizzle_result_free(&result);
2197
} /* getTableName */
342
2200
static int dump_all_databases()
344
2202
drizzle_row_t row;
345
drizzle_result_st *tableres;
2203
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)))
2206
if (drizzleclient_query_with_error_report(&dcon, &tableres, "SHOW DATABASES", false))
2208
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);
2210
if (dump_all_tables_in_db(row[0]))
371
db_connection->freeResult(tableres);
2213
drizzle_result_free(&tableres);
374
2216
/* dump_all_databases */
377
static int dump_databases(const vector<string> &db_names)
2219
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)
2225
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);
2227
if (dump_all_tables_in_db(*db))
393
2231
} /* 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);
2235
Table Specific database initalization.
2239
qdatabase quoted name of the database
2246
int init_dumping_tables(char *qdatabase)
2252
drizzle_result_st result;
2253
drizzle_return_t ret;
2255
snprintf(qbuf, sizeof(qbuf),
2256
"SHOW CREATE DATABASE IF NOT EXISTS %s",
2259
if (drizzle_query_str(&dcon, &result, qbuf, &ret) == NULL ||
2260
ret != DRIZZLE_RETURN_OK)
2262
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2263
drizzle_result_free(&result);
2265
/* Old server version, dump generic CREATE DATABASE */
2266
if (opt_drop_database)
2267
fprintf(md_result_file,
2268
"\nDROP DATABASE IF EXISTS %s;\n",
2270
fprintf(md_result_file,
2271
"\nCREATE DATABASE IF NOT EXISTS %s;\n",
2276
if (drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
2278
if (opt_drop_database)
2279
fprintf(md_result_file,
2280
"\nDROP DATABASE IF EXISTS %s;\n",
2282
row = drizzle_row_next(&result);
2283
if (row != NULL && row[1])
2285
fprintf(md_result_file,"\n%s;\n",row[1]);
2288
drizzle_result_free(&result);
2292
} /* init_dumping_tables */
2295
static int init_dumping(char *database, int init_func(char*))
2297
drizzle_result_st result;
2298
drizzle_return_t ret;
2300
if (!my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
2303
if (drizzle_select_db(&dcon, &result, database, &ret) == NULL ||
2304
ret != DRIZZLE_RETURN_OK)
2306
DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
2307
return 1; /* If --force */
2309
drizzle_result_free(&result);
2311
if (!path && !opt_xml)
2313
if (opt_databases || opt_alldbs)
2316
length of table name * 2 (if name contains quotes), 2 quotes and 0
2318
char quoted_database_buf[DRIZZLE_MAX_DB_SIZE*2+3];
2319
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
2322
fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
2323
check_io(md_result_file);
2326
/* Call the view or table specific function */
2327
init_func(qdatabase);
2329
fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
2330
check_io(md_result_file);
2333
if (extended_insert)
2334
extended_row.clear();
2336
} /* init_dumping */
2339
/* Return 1 if we should copy the table */
2341
static bool include_table(const char *hash_key, size_t key_size)
2343
string match(hash_key, key_size);
2344
unordered_set<string>::iterator iter= ignore_table.find(match);
2345
return (iter == ignore_table.end());
2349
static int dump_all_tables_in_db(char *database)
2352
char hash_key[DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2]; /* "db.tablename" */
2354
drizzle_result_st result;
2355
drizzle_return_t ret;
2357
memset(hash_key, 0, DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2);
2358
afterdot= strcpy(hash_key, database) + strlen(database);
2361
if (init_dumping(database, init_dumping_tables))
2364
print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NULL);
2367
if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
2368
ret != DRIZZLE_RETURN_OK)
2370
DB_error(&result, ret, _("when doing refresh"));
2371
/* We shall continue here, if --force was given */
2374
drizzle_result_free(&result);
2376
while ((table= getTableName(0)))
2378
char *end= strcpy(afterdot, table) + strlen(table);
2379
if (include_table(hash_key, end - hash_key))
2381
dump_table(table,database);
2388
fputs("</database>\n", md_result_file);
2389
check_io(md_result_file);
2393
} /* dump_all_tables_in_db */
2397
get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
2398
table name from the server for the table name given on the command line.
2399
we do this because the table name given on the command line may be a
2400
different case (e.g. T1 vs t1)
2403
pointer to the table name
2407
static char *get_actual_table_name(const char *old_table_name,
2408
drizzled::memory::Root *root)
2411
drizzle_result_st result;
2413
char query[50 + 2*DRIZZLE_MAX_TABLE_SIZE];
2414
char show_name_buff[FN_REFLEN];
2418
/* Check memory for quote_for_like() */
2419
assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
2420
snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
2421
quote_for_like(old_table_name, show_name_buff));
2423
if (drizzleclient_query_with_error_report(&dcon, &result, query, false))
2426
num_rows= drizzle_result_row_count(&result);
2432
TODO-> Return all matching rows
2434
row= drizzle_row_next(&result);
2435
lengths= drizzle_row_field_sizes(&result);
2436
name= root->strmake_root(row[0], lengths[0]);
2438
drizzle_result_free(&result);
2444
static int dump_selected_tables(char *db, char **table_names, int tables)
2446
drizzled::memory::Root root;
2447
char **dump_tables, **pos, **end;
2448
drizzle_result_st result;
2449
drizzle_return_t ret;
2452
if (init_dumping(db, init_dumping_tables))
2455
root.init_alloc_root(8192);
2456
if (!(dump_tables= pos= (char**) root.alloc_root(tables * sizeof(char *))))
2457
die(EX_EOM, _("alloc_root failure."));
2459
for (; tables > 0 ; tables-- , table_names++)
2461
/* the table name passed on commandline may be wrong case */
2462
if ((*pos= get_actual_table_name(*table_names, &root)))
2470
root.free_root(MYF(0));
2472
maybe_die(EX_ILLEGAL_TABLE, _("Couldn't find table: \"%s\""), *table_names);
2473
/* We shall countinue here, if --force was given */
2480
if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
2481
ret != DRIZZLE_RETURN_OK)
2484
root.free_root(MYF(0));
2485
DB_error(&result, ret, _("when doing refresh"));
2486
/* We shall countinue here, if --force was given */
2489
drizzle_result_free(&result);
2492
print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NULL);
2494
/* Dump each selected table */
2495
for (pos= dump_tables; pos < end; pos++)
2496
dump_table(*pos, db);
2498
root.free_root(MYF(0));
2503
fputs("</database>\n", md_result_file);
2504
check_io(md_result_file);
414
2507
} /* dump_selected_tables */
416
static int do_flush_tables_read_lock()
2509
static int do_flush_tables_read_lock(drizzle_con_st *drizzle_con)
419
2512
We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
423
2516
and most client connections are stalled. Of course, if a second long
424
2517
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");
2520
( drizzleclient_query_with_error_report(drizzle_con, 0, "FLUSH TABLES", false) ||
2521
drizzleclient_query_with_error_report(drizzle_con, 0,
2522
"FLUSH TABLES WITH READ LOCK", false) );
2525
static int do_unlock_tables(drizzle_con_st *drizzle_con)
2527
return drizzleclient_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES", false);
2530
static int start_transaction(drizzle_con_st *drizzle_con)
2532
return (drizzleclient_query_with_error_report(drizzle_con, 0,
2533
"SET SESSION TRANSACTION ISOLATION "
2534
"LEVEL REPEATABLE READ", false) ||
2535
drizzleclient_query_with_error_report(drizzle_con, 0,
2536
"START TRANSACTION "
2537
"WITH CONSISTENT SNAPSHOT", false));
2541
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
2542
char **err_pos, uint32_t *err_len)
2544
const char *end= x + length;
2549
*err_pos= 0; /* No error yet */
2550
while (end > x && my_isspace(charset_info, end[-1]))
2556
const char *start= x;
2559
const char *pos= start;
2562
for (; pos != end && *pos != ','; pos++) ;
2563
var_len= (uint32_t) (pos - start);
2564
strncpy(buff, start, min((uint32_t)sizeof(buff), var_len+1));
2565
find= find_type(buff, lib, var_len);
2568
*err_pos= (char*) start;
2572
found|= (uint32_t)((int64_t) 1 << (find - 1));
2582
/* Print a value with a prefix on file */
2583
static void print_value(FILE *file, drizzle_result_st *result, drizzle_row_t row,
2584
const char *prefix, const char *name,
2587
drizzle_column_st *column;
2588
drizzle_column_seek(result, 0);
2590
for ( ; (column= drizzle_column_next(result)) ; row++)
2592
if (!strcmp(drizzle_column_name(column),name))
2594
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
2597
fputs(prefix, file);
2599
unescape(file,row[0],(uint32_t) strlen(row[0]));
2601
fputs(row[0], file);
2607
return; /* This shouldn't happen */
2611
* Fetches a row from a result based on a field name
2612
* Returns const char* of the data in that row or NULL if not found
2615
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row, const char *name)
2617
drizzle_column_st *column;
2618
drizzle_column_seek(result, 0);
2620
for ( ; (column= drizzle_column_next(result)) ; row++)
2622
if (!strcmp(drizzle_column_name(column),name))
2624
if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
2626
drizzle_column_seek(result, 0);
2631
drizzle_column_seek(result, 0);
2639
Check if we the table is one of the table types that should be ignored:
2640
MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
2641
If the table should be altogether ignored, it returns a true, false if it
2642
should not be ignored. If the user has selected to use INSERT DELAYED, it
2643
sets the value of the bool pointer supports_delayed_inserts to 0 if not
2644
supported, 1 if it is supported.
2648
check_if_ignore_table()
2649
table_name Table name to check
2650
table_type Type of table
2653
drizzle Drizzle connection
2654
verbose Write warning messages
2657
char (bit value) See IGNORE_ values at top
2660
char check_if_ignore_table(const char *table_name, char *table_type)
2662
char result= IGNORE_NONE;
2663
char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
2664
const char *number_of_rows= NULL;
2665
drizzle_result_st res;
2668
/* Check memory for quote_for_like() */
2669
assert(2*sizeof(table_name) < sizeof(show_name_buff));
2670
snprintf(buff, sizeof(buff), "show table status like %s",
2671
quote_for_like(table_name, show_name_buff));
2672
if (drizzleclient_query_with_error_report(&dcon, &res, buff, false))
2676
if (!(row= drizzle_row_next(&res)))
2679
_("Error: Couldn't read status information for table %s\n"),
2681
drizzle_result_free(&res);
2682
return(result); /* assume table is ok */
2686
if ((number_of_rows= fetch_named_row(&res, row, "Rows")) != NULL)
2688
total_rows= strtoul(number_of_rows, NULL, 10);
2692
If the table type matches any of these, we do support delayed inserts.
2693
Note-> we do not want to skip dumping this table if if is not one of
2694
these types, but we do want to use delayed inserts in the dump if
2695
the table type is _NOT_ one of these types
2698
strncpy(table_type, row[1], DRIZZLE_MAX_TABLE_SIZE-1);
2701
if (strcmp(table_type,"MyISAM") &&
2702
strcmp(table_type,"ARCHIVE") &&
2703
strcmp(table_type,"HEAP") &&
2704
strcmp(table_type,"MEMORY"))
2705
result= IGNORE_INSERT_DELAYED;
2708
drizzle_result_free(&res);
2714
Get string of comma-separated primary key field names
2717
char *primary_key_fields(const char *table_name)
2718
RETURNS pointer to allocated buffer (must be freed by caller)
2719
table_name quoted table name
2722
Use SHOW KEYS FROM table_name, allocate a buffer to hold the
2723
field names, and then build that string and return the pointer
2726
Returns NULL if there is no PRIMARY or UNIQUE key on the table,
2727
or if there is some failure. It is better to continue to dump
2728
the table unsorted, rather than exit without dumping the data.
2731
static char *primary_key_fields(const char *table_name)
2733
drizzle_result_st res;
2734
drizzle_return_t ret;
2736
/* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
2737
char show_keys_buff[15 + DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
2738
uint32_t result_length= 0;
2740
char buff[DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
2743
snprintf(show_keys_buff, sizeof(show_keys_buff),
2744
"SHOW KEYS FROM %s", table_name);
2745
if (drizzle_query_str(&dcon, &res, show_keys_buff, &ret) == NULL ||
2746
ret != DRIZZLE_RETURN_OK)
2748
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2750
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2751
" records are NOT sorted (%s)\n"),
2752
table_name, drizzle_result_error(&res));
2753
drizzle_result_free(&res);
2757
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2758
" records are NOT sorted (%s)\n"),
2759
table_name, drizzle_con_error(&dcon));
2765
if (drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
2767
fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
2768
" records are NOT sorted (%s)\n"),
2769
table_name, drizzle_con_error(&dcon));
2774
* Figure out the length of the ORDER BY clause result.
2775
* Note that SHOW KEYS is ordered: a PRIMARY key is always the first
2776
* row, and UNIQUE keys come before others. So we only need to check
2777
* the first key, not all keys.
2779
if ((row= drizzle_row_next(&res)) && atoi(row[1]) == 0)
2784
quoted_field= quote_name(row[4], buff, 0);
2785
result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
2786
} while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1);
2789
/* Build the ORDER BY clause result */
2793
/* result (terminating \0 is already in result_length) */
2795
size_t result_length_alloc= result_length + 10;
2796
result= (char *)malloc(result_length_alloc);
2799
fprintf(stderr, _("Error: Not enough memory to store ORDER BY clause\n"));
2800
drizzle_result_free(&res);
2803
drizzle_row_seek(&res, 0);
2804
row= drizzle_row_next(&res);
2805
quoted_field= quote_name(row[4], buff, 0);
2806
end= strcpy(result, quoted_field) + strlen(quoted_field);
2807
result_length_alloc -= strlen(quoted_field);
2808
while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1)
2810
quoted_field= quote_name(row[4], buff, 0);
2811
end+= snprintf(end, result_length_alloc, ",%s",quoted_field);
2812
result_length_alloc -= strlen(quoted_field);
2816
drizzle_result_free(&res);
446
2821
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();
2824
MY_INIT("drizzledump");
2825
drizzle_result_st result;
2827
compatible_mode_normal_str[0]= 0;
2829
exit_code= get_options(&argc, &argv);
732
2832
free_resources();
733
2833
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())
2836
if (connect_to_db(current_host, current_user, opt_password))
2839
exit(EX_DRIZZLEERR);
2842
write_header(md_result_file, *argv);
2844
if ((opt_lock_all_tables) && do_flush_tables_read_lock(&dcon))
768
if (opt_single_transaction && start_transaction())
2846
if (opt_single_transaction && start_transaction(&dcon))
770
2848
if (opt_lock_all_tables)
771
db_connection->queryNoResult("FLUSH LOGS");
772
if (opt_single_transaction && do_unlock_tables()) /* unlock but no commit! */
2850
if (drizzleclient_query_with_error_report(&dcon, &result, "FLUSH LOGS", false))
2852
drizzle_result_free(&result);
2853
flush_logs= 0; /* not anymore; that would not be sensible */
2855
if (opt_single_transaction && do_unlock_tables(&dcon)) /* unlock but no commit! */
777
2860
dump_all_databases();
780
if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
2862
else if (argc > 1 && !opt_databases)
782
string database_used= *vm["database-used"].as< vector<string> >().begin();
783
2864
/* 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)
2865
dump_selected_tables(*argv, (argv + 1), (argc - 1));
2869
dump_databases(argv);
814
2872
/* ensure dumped data flushed */
815
2873
if (md_result_file && fflush(md_result_file))