~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

mergeĀ mainline

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
2
 
 * Copyright (C) 2010 Vijay Samuel
3
 
 * Copyright (C) 2010 Andrew Hutchings
4
 
 
5
 
  This program is free software; you can redistribute it and/or modify
6
 
  it under the terms of the GNU General Public License as published by
7
 
  the Free Software Foundation; version 2 of the License.
8
 
 
9
 
  This program is distributed in the hope that it will be useful,
10
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
  GNU General Public License for more details.
13
 
 
14
 
  You should have received a copy of the GNU General Public License
15
 
  along with this program; if not, write to the Free Software
16
 
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
1
/* Copyright (C) 2008 Drizzle Open Source Development Project
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
17
15
 
18
16
/* drizzledump.cc  - Dump a tables contents and format to an ASCII file
19
 
 
20
 
 * Derived from mysqldump, which originally came from:
21
 
 **
22
 
 ** The author's original notes follow :-
23
 
 **
24
 
 ** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
25
 
 ** DATE:   December 3, 1994
26
 
 ** WARRANTY: None, expressed, impressed, implied
27
 
 **          or other
28
 
 ** STATUS: Public domain
29
 
 
30
 
 * and more work by Monty, Jani & Sinisa
31
 
 * and all the MySQL developers over the years.
 
17
**
 
18
** The author's original notes follow :-
 
19
**
 
20
** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
 
21
** DATE:   December 3, 1994
 
22
** WARRANTY: None, expressed, impressed, implied
 
23
**          or other
 
24
** STATUS: Public domain
32
25
*/
33
26
 
 
27
#define DUMP_VERSION "10.13"
 
28
 
34
29
#include "client_priv.h"
35
30
#include <string>
36
 
#include <iostream>
 
31
 
 
32
#include <mysys/my_sys.h>
 
33
#include <mystrings/m_string.h>
 
34
#include <mystrings/m_ctype.h>
 
35
#include <mysys/hash.h>
37
36
#include <stdarg.h>
38
 
#include <boost/unordered_set.hpp>
39
37
#include <algorithm>
40
 
#include <fstream>
 
38
 
41
39
#include <drizzled/gettext.h>
42
 
#include <drizzled/configmake.h>
 
40
 
43
41
#include <drizzled/error.h>
44
 
#include <boost/program_options.hpp>
45
 
#include <boost/regex.hpp>
46
 
#include <boost/date_time/posix_time/posix_time.hpp>
47
 
#include "drizzledump_data.h"
48
 
#include "drizzledump_mysql.h"
49
 
#include "drizzledump_drizzle.h"
50
42
 
51
43
using namespace std;
52
 
using namespace drizzled;
53
 
namespace po= boost::program_options;
54
 
 
55
44
/* Exit codes */
56
45
 
57
46
#define EX_USAGE 1
78
67
#define IGNORE_DATA 0x01 /* don't dump data for this table */
79
68
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
80
69
 
81
 
bool opt_alltspcs= false;
82
 
bool opt_complete_insert= false;
83
 
bool  verbose= false;
84
 
static bool use_drizzle_protocol= false;
85
 
bool ignore_errors= false;
86
 
static bool flush_logs= false;
87
 
static bool create_options= true; 
88
 
static bool opt_quoted= false;
89
 
bool opt_databases= false; 
90
 
bool opt_alldbs= false; 
91
 
static bool opt_lock_all_tables= false;
92
 
static bool opt_dump_date= true;
93
 
bool opt_autocommit= false; 
94
 
static bool opt_single_transaction= false; 
95
 
static bool opt_comments;
96
 
static bool opt_compact;
97
 
bool opt_ignore= false;
98
 
bool opt_drop_database;
99
 
bool opt_no_create_info;
100
 
bool opt_no_data= false;
101
 
bool opt_create_db= false;
102
 
bool opt_disable_keys= true;
103
 
bool extended_insert= true;
104
 
bool opt_replace_into= false;
105
 
bool opt_drop= true; 
106
 
uint32_t show_progress_size= 0;
 
70
static void add_load_option(string &str, const char *option,
 
71
                            const char *option_value);
 
72
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
 
73
                      char **err_pos, uint32_t *err_len);
 
74
 
 
75
static void field_escape(string &in, const char *from);
 
76
static bool  verbose= false, opt_no_create_info= false, opt_no_data= false,
 
77
                quick= true, extended_insert= true,
 
78
                lock_tables= true, ignore_errors= false, flush_logs= false,
 
79
                opt_drop= true, opt_keywords= false,
 
80
                opt_lock= true, opt_compress= false,
 
81
                opt_delayed= false, create_options= true, opt_quoted= false,
 
82
                opt_databases= false, opt_alldbs= false, opt_create_db= false,
 
83
                opt_lock_all_tables= false,
 
84
                opt_set_charset= false, opt_dump_date= true,
 
85
                opt_autocommit= false, opt_disable_keys= true, opt_xml= false,
 
86
                opt_delete_master_logs= false, tty_password= false,
 
87
                opt_single_transaction= false, opt_comments= false,
 
88
                opt_compact= false, opt_hex_blob= false, 
 
89
                opt_order_by_primary=false, opt_ignore= false,
 
90
                opt_complete_insert= false, opt_drop_database= false,
 
91
                opt_replace_into= false,
 
92
                opt_routines= false,
 
93
                opt_slave_apply= false,
 
94
                opt_include_master_host_port= false,
 
95
                opt_alltspcs= false;
 
96
static bool debug_info_flag= false, debug_check_flag= false;
 
97
static uint32_t opt_max_allowed_packet, opt_net_buffer_length, show_progress_size= 0;
 
98
static uint64_t total_rows= 0;
 
99
static DRIZZLE drizzleclient_connection, *drizzle= 0;
107
100
static string insert_pat;
 
101
static char  *opt_password= NULL, *current_user= NULL,
 
102
             *current_host= NULL, *path= NULL, *fields_terminated= NULL,
 
103
             *lines_terminated= NULL, *enclosed= NULL, *opt_enclosed= NULL,
 
104
             *escaped= NULL,
 
105
             *where= NULL, *order_by= NULL,
 
106
             *opt_compatible_mode_str= NULL,
 
107
             *err_ptr= NULL;
 
108
static char **defaults_argv= NULL;
 
109
static char compatible_mode_normal_str[255];
 
110
static uint32_t opt_compatible_mode= 0;
 
111
#define DRIZZLE_OPT_MASTER_DATA_EFFECTIVE_SQL 1
 
112
#define DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL 2
 
113
#define DRIZZLE_OPT_SLAVE_DATA_EFFECTIVE_SQL 1
 
114
#define DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL 2
108
115
static uint32_t opt_drizzle_port= 0;
 
116
static uint32_t opt_master_data;
 
117
static uint32_t opt_slave_data;
 
118
static uint32_t my_end_arg;
109
119
static int first_error= 0;
110
120
static string extended_row;
111
121
FILE *md_result_file= 0;
112
122
FILE *stderror_file= 0;
113
 
std::vector<DrizzleDumpDatabase*> database_store;
114
 
DrizzleDumpConnection* db_connection;
115
 
DrizzleDumpConnection* destination_connection;
116
 
 
117
 
enum destinations {
118
 
  DESTINATION_DB,
119
 
  DESTINATION_FILES,
120
 
  DESTINATION_STDOUT
121
 
};
122
 
 
123
 
int opt_destination= DESTINATION_STDOUT;
124
 
std::string opt_destination_host;
125
 
uint16_t opt_destination_port;
126
 
std::string opt_destination_user;
127
 
std::string opt_destination_password;
128
 
std::string opt_destination_database;
129
 
 
130
 
const string progname= "drizzledump";
131
 
 
132
 
string password,
133
 
  enclosed,
134
 
  escaped,
135
 
  current_host,
136
 
  path,
137
 
  current_user,
138
 
  opt_password,
139
 
  opt_protocol,
140
 
  where;
141
 
 
142
 
//static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
143
 
 
144
 
boost::unordered_set<string> ignore_table;
145
 
 
146
 
void maybe_exit(int error);
 
123
 
 
124
/*
 
125
  Constant for detection of default value of default_charset.
 
126
  If default_charset is equal to drizzle_universal_client_charset, then
 
127
  it is the default value which assigned at the very beginning of main().
 
128
*/
 
129
static const char *drizzle_universal_client_charset=
 
130
  DRIZZLE_UNIVERSAL_CLIENT_CHARSET;
 
131
static char *default_charset;
 
132
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
 
133
const char *default_dbug_option="d:t:o,/tmp/drizzledump.trace";
 
134
const char *compatible_mode_names[]=
 
135
{
 
136
  "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
 
137
  "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
 
138
  "ANSI",
 
139
  NULL
 
140
};
 
141
#define MASK_ANSI_QUOTES \
 
142
(\
 
143
 (1<<2)  | /* POSTGRESQL */\
 
144
 (1<<3)  | /* ORACLE     */\
 
145
 (1<<4)  | /* MSSQL      */\
 
146
 (1<<5)  | /* DB2        */\
 
147
 (1<<6)  | /* MAXDB      */\
 
148
 (1<<10)   /* ANSI       */\
 
149
)
 
150
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
 
151
                                  "", compatible_mode_names, NULL};
 
152
 
 
153
HASH ignore_table;
 
154
 
 
155
static struct my_option my_long_options[] =
 
156
{
 
157
  {"all", 'a', "Deprecated. Use --create-options instead.",
 
158
   (char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
 
159
   0, 0, 0, 0, 0},
 
160
  {"all-databases", 'A',
 
161
   "Dump all the databases. This will be same as --databases with all databases selected.",
 
162
   (char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
163
   0, 0},
 
164
  {"all-tablespaces", 'Y',
 
165
   "Dump all the tablespaces.",
 
166
   (char**) &opt_alltspcs, (char**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
167
   0, 0},
 
168
  {"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
 
169
   (char**) &opt_drop_database, (char**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
 
170
   0},
 
171
  {"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
 
172
   (char**) &opt_drop, (char**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
 
173
   0},
 
174
  {"add-locks", OPT_LOCKS, "Add locks around insert statements.",
 
175
   (char**) &opt_lock, (char**) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
 
176
   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
  {"apply-slave-statements", OPT_DRIZZLEDUMP_SLAVE_APPLY,
 
181
   "Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
 
182
   (char**) &opt_slave_apply, (char**) &opt_slave_apply, 0, GET_BOOL, NO_ARG,
 
183
   0, 0, 0, 0, 0, 0},
 
184
  {"comments", 'i', "Write additional information.",
 
185
   (char**) &opt_comments, (char**) &opt_comments, 0, GET_BOOL, NO_ARG,
 
186
   1, 0, 0, 0, 0, 0},
 
187
  {"compatible", OPT_COMPATIBLE,
 
188
   "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.",
 
189
   (char**) &opt_compatible_mode_str, (char**) &opt_compatible_mode_str, 0,
 
190
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
191
  {"compact", OPT_COMPACT,
 
192
   "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",
 
193
   (char**) &opt_compact, (char**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
194
   0, 0},
 
195
  {"complete-insert", 'c', "Use complete insert statements.",
 
196
   (char**) &opt_complete_insert, (char**) &opt_complete_insert, 0, GET_BOOL,
 
197
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
198
  {"compress", 'C', "Use compression in server/client protocol.",
 
199
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
200
   0, 0, 0},
 
201
  {"create-options", OPT_CREATE_OPTIONS,
 
202
   "Include all DRIZZLE specific create options.",
 
203
   (char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
 
204
   0, 0, 0, 0, 0},
 
205
  {"databases", 'B',
 
206
   "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.",
 
207
   (char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
 
208
   0, 0, 0, 0},
 
209
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
 
210
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
 
211
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
212
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
 
213
   (char**) &debug_info_flag, (char**) &debug_info_flag,
 
214
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
215
  {"default-character-set", OPT_DEFAULT_CHARSET,
 
216
   "Set the default character set.", (char**) &default_charset,
 
217
   (char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
218
  {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
 
219
   (char**) &opt_delayed, (char**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
220
   0, 0},
 
221
  {"delete-master-logs", OPT_DELETE_MASTER_LOGS,
 
222
   "Delete logs on master after backup. This automatically enables --master-data.",
 
223
   (char**) &opt_delete_master_logs, (char**) &opt_delete_master_logs, 0,
 
224
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
225
  {"disable-keys", 'K',
 
226
   "'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will be put in the output.", (char**) &opt_disable_keys,
 
227
   (char**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
228
  {"dump-slave", OPT_DRIZZLEDUMP_SLAVE_DATA,
 
229
   "This causes the binary log position and filename of the master to be "
 
230
   "appended to the dumped data output. Setting the value to 1, will print"
 
231
   "it as a CHANGE MASTER command in the dumped data output; if equal"
 
232
   " to 2, that command will be prefixed with a comment symbol. "
 
233
   "This option will turn --lock-all-tables on, unless "
 
234
   "--single-transaction is specified too (in which case a "
 
235
   "global read lock is only taken a short time at the beginning of the dump "
 
236
   "- don't forget to read about --single-transaction below). In all cases "
 
237
   "any action on logs will happen at the exact moment of the dump."
 
238
   "Option automatically turns --lock-tables off.",
 
239
   (char**) &opt_slave_data, (char**) &opt_slave_data, 0,
 
240
   GET_UINT, OPT_ARG, 0, 0, DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0},
 
241
  {"extended-insert", 'e',
 
242
   "Allows utilization of the new, much faster INSERT syntax.",
 
243
   (char**) &extended_insert, (char**) &extended_insert, 0, GET_BOOL, NO_ARG,
 
244
   1, 0, 0, 0, 0, 0},
 
245
  {"fields-terminated-by", OPT_FTB,
 
246
   "Fields in the textfile are terminated by ...", (char**) &fields_terminated,
 
247
   (char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
248
  {"fields-enclosed-by", OPT_ENC,
 
249
   "Fields in the importfile are enclosed by ...", (char**) &enclosed,
 
250
   (char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
 
251
  {"fields-optionally-enclosed-by", OPT_O_ENC,
 
252
   "Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
 
253
   (char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
 
254
  {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
 
255
   (char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
256
  {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
 
257
   (char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
 
258
   0, 0, 0, 0, 0, 0},
 
259
  {"flush-logs", 'F', "Flush logs file in server before starting dump. "
 
260
   "Note that if you dump many databases at once (using the option "
 
261
   "--databases= or --all-databases), the logs will be flushed for "
 
262
   "each database dumped. The exception is when using --lock-all-tables "
 
263
   "or --master-data: "
 
264
   "in this case the logs will be flushed only once, corresponding "
 
265
   "to the moment all tables are locked. So if you want your dump and "
 
266
   "the log flush to happen at the same exact moment you should use "
 
267
   "--lock-all-tables or --master-data with --flush-logs",
 
268
   (char**) &flush_logs, (char**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
269
   0, 0},
 
270
  {"force", 'f', "Continue even if we get an sql-error.",
 
271
   (char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG,
 
272
   0, 0, 0, 0, 0, 0},
 
273
  {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
 
274
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
275
  {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
 
276
    "VARBINARY, BLOB) in hexadecimal format.",
 
277
   (char**) &opt_hex_blob, (char**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
278
  {"host", 'h', "Connect to host.", (char**) &current_host,
 
279
   (char**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
280
  {"ignore-table", OPT_IGNORE_TABLE,
 
281
   "Do not dump the specified table. To specify more than one table to ignore, "
 
282
   "use the directive multiple times, once for each table.  Each table must "
 
283
   "be specified with both database and table names, e.g. --ignore-table=database.table",
 
284
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
285
  {"include-master-host-port", OPT_DRIZZLEDUMP_INCLUDE_MASTER_HOST_PORT,
 
286
   "Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' in dump produced with --dump-slave.",
 
287
   (char**) &opt_include_master_host_port,
 
288
   (char**) &opt_include_master_host_port,
 
289
   0, GET_BOOL, NO_ARG,
 
290
   0, 0, 0, 0, 0, 0},
 
291
  {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
 
292
   (char**) &opt_ignore, (char**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
293
   0, 0},
 
294
  {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
 
295
   (char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
 
296
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
297
  {"lock-all-tables", 'x', "Locks all tables across all databases. This "
 
298
   "is achieved by taking a global read lock for the duration of the whole "
 
299
   "dump. Automatically turns --single-transaction and --lock-tables off.",
 
300
   (char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
 
301
   0, 0, 0, 0, 0, 0},
 
302
  {"lock-tables", 'l', "Lock all tables for read.", (char**) &lock_tables,
 
303
   (char**) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
304
  {"master-data", OPT_MASTER_DATA,
 
305
   "This causes the binary log position and filename to be appended to the "
 
306
   "output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
 
307
   " to 2, that command will be prefixed with a comment symbol. "
 
308
   "This option will turn --lock-all-tables on, unless "
 
309
   "--single-transaction is specified too (in which case a "
 
310
   "global read lock is only taken a short time at the beginning of the dump "
 
311
   "- don't forget to read about --single-transaction below). In all cases "
 
312
   "any action on logs will happen at the exact moment of the dump."
 
313
   "Option automatically turns --lock-tables off.",
 
314
   (char**) &opt_master_data, (char**) &opt_master_data, 0,
 
315
   GET_UINT, OPT_ARG, 0, 0, DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
 
316
  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
 
317
    (char**) &opt_max_allowed_packet, (char**) &opt_max_allowed_packet, 0,
 
318
    GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
 
319
   (int64_t) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
 
320
  {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
 
321
    (char**) &opt_net_buffer_length, (char**) &opt_net_buffer_length, 0,
 
322
    GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
 
323
   MALLOC_OVERHEAD-1024, 1024, 0},
 
324
  {"no-autocommit", OPT_AUTOCOMMIT,
 
325
   "Wrap tables with autocommit/commit statements.",
 
326
   (char**) &opt_autocommit, (char**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
 
327
   0, 0, 0, 0, 0, 0},
 
328
  {"no-create-db", 'n',
 
329
   "'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.}.",
 
330
   (char**) &opt_create_db, (char**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
 
331
   0, 0, 0, 0},
 
332
  {"no-create-info", 't', "Don't write table creation info.",
 
333
   (char**) &opt_no_create_info, (char**) &opt_no_create_info, 0, GET_BOOL,
 
334
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
335
  {"no-data", 'd', "No row information.", (char**) &opt_no_data,
 
336
   (char**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
337
  {"no-set-names", 'N',
 
338
   "Deprecated. Use --skip-set-charset instead.",
 
339
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
340
  {"opt", OPT_OPTIMIZE,
 
341
   "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.",
 
342
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
343
  {"order-by-primary", OPT_ORDER_BY_PRIMARY,
 
344
   "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.",
 
345
   (char**) &opt_order_by_primary, (char**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
346
  {"password", 'P',
 
347
   "Password to use when connecting to server. If password is not given it's solicited on the tty.",
 
348
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
349
  {"port", 'p', "Port number to use for connection.", 
 
350
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
351
  {"quick", 'q', "Don't buffer query, dump directly to stdout.",
 
352
   (char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
353
  {"quote-names",'Q', "Quote table and column names with backticks (`).",
 
354
   (char**) &opt_quoted, (char**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
 
355
   0, 0},
 
356
  {"replace", OPT_DRIZZLE_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
 
357
   (char**) &opt_replace_into, (char**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
358
   0, 0},
 
359
  {"result-file", 'r',
 
360
   "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).",
 
361
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
362
  {"routines", 'R', "Dump stored routines (functions and procedures).",
 
363
     (char**) &opt_routines, (char**) &opt_routines, 0, GET_BOOL,
 
364
     NO_ARG, 0, 0, 0, 0, 0, 0},
 
365
  /*
 
366
    Note that the combination --single-transaction --master-data
 
367
    will give bullet-proof binlog position only if server >=4.1.3. That's the
 
368
    old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug.
 
369
  */
 
370
  {"single-transaction", OPT_TRANSACTION,
 
371
   "Creates a consistent snapshot by dumping all tables in a single "
 
372
   "transaction. Works ONLY for tables stored in storage engines which "
 
373
   "support multiversioning (currently only InnoDB does); the dump is NOT "
 
374
   "guaranteed to be consistent for other storage engines. "
 
375
   "While a --single-transaction dump is in process, to ensure a valid "
 
376
   "dump file (correct table contents and binary log position), no other "
 
377
   "connection should use the following statements: ALTER TABLE, DROP "
 
378
   "TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
 
379
   "isolated from them. Option automatically turns off --lock-tables.",
 
380
   (char**) &opt_single_transaction, (char**) &opt_single_transaction, 0,
 
381
   GET_BOOL, NO_ARG,  0, 0, 0, 0, 0, 0},
 
382
  {"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
 
383
   (char**) &opt_dump_date, (char**) &opt_dump_date, 0,
 
384
   GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
385
  {"skip-opt", OPT_SKIP_OPTIMIZATION,
 
386
   "Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
 
387
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
388
  {"tab",'T',
 
389
   "Creates tab separated textfile for each table to given path. (creates .sql and .txt files). NOTE: This only works if mysqldump is run on the same machine as the mysqld daemon.",
 
390
   (char**) &path, (char**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
391
  {"tables", OPT_TABLES, "Overrides option --databases (-B).",
 
392
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
393
  {"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of rows before each output progress report (requires --verbose)."),
 
394
   (char**) &show_progress_size, (char**) &show_progress_size, 0, GET_ULONG, REQUIRED_ARG,
 
395
   10000, 0, 0, 0, 0, 0},
 
396
#ifndef DONT_ALLOW_USER_CHANGE
 
397
  {"user", 'u', "User for login if not current user.",
 
398
   (char**) &current_user, (char**) &current_user, 0, GET_STR, REQUIRED_ARG,
 
399
   0, 0, 0, 0, 0, 0},
 
400
#endif
 
401
  {"verbose", 'v', "Print info about the various stages.",
 
402
   (char**) &verbose, (char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
403
  {"version",'V', "Output version information and exit.", 0, 0, 0,
 
404
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
405
  {"where", 'w', "Dump only selected records; QUOTES mandatory!",
 
406
   (char**) &where, (char**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
407
  {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
 
408
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
409
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
410
};
 
411
 
 
412
static const char *load_default_groups[]= { "drizzledump","client",0 };
 
413
 
 
414
static void maybe_exit(int error);
147
415
static void die(int error, const char* reason, ...);
148
 
static void write_header(char *db_name);
149
 
static int dump_selected_tables(const string &db, const vector<string> &table_names);
150
 
static int dump_databases(const vector<string> &db_names);
 
416
static void maybe_die(int error, const char* reason, ...);
 
417
static void write_header(FILE *sql_file, char *db_name);
 
418
static void print_value(FILE *file, DRIZZLE_RES  *result, DRIZZLE_ROW row,
 
419
                        const char *prefix,const char *name,
 
420
                        int string_value);
 
421
static const char* fetch_named_row(DRIZZLE_RES *result, DRIZZLE_ROW row, const char* name);
 
422
static int dump_selected_tables(char *db, char **table_names, int tables);
 
423
static int dump_all_tables_in_db(char *db);
 
424
static int init_dumping_tables(char *);
 
425
static int init_dumping(char *, int init_func(char*));
 
426
static int dump_databases(char **);
151
427
static int dump_all_databases(void);
152
 
int get_server_type();
153
 
void dump_all_tables(void);
154
 
void generate_dump(void);
155
 
void generate_dump_db(void);
156
 
 
157
 
void dump_all_tables(void)
158
 
{
159
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
160
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
161
 
  {
162
 
    if ((not (*i)->populateTables()) && (not ignore_errors))
163
 
      maybe_exit(EX_DRIZZLEERR);
164
 
  }
165
 
}
166
 
 
167
 
void generate_dump(void)
168
 
{
169
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
170
 
 
171
 
  if (path.empty())
172
 
  {
173
 
    cout << endl << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;"
174
 
      << endl << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
175
 
  }
176
 
 
177
 
  if (opt_autocommit)
178
 
    cout << "SET AUTOCOMMIT=0;" << endl;
179
 
 
180
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
181
 
  {
182
 
    DrizzleDumpDatabase *database= *i;
183
 
    cout << *database;
184
 
  }
185
 
 
186
 
  if (path.empty())
187
 
  {
188
 
    cout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;"
189
 
      << endl << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
190
 
  }
191
 
}
192
 
 
193
 
void generate_dump_db(void)
194
 
{
195
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
196
 
  DrizzleStringBuf sbuf(1024);
197
 
  try
198
 
  {
199
 
    destination_connection= new DrizzleDumpConnection(opt_destination_host,
200
 
      opt_destination_port, opt_destination_user, opt_destination_password,
201
 
      false);
202
 
  }
203
 
  catch (std::exception&)
204
 
  {
205
 
    cerr << "Could not connect to destination database server" << endl;
206
 
    maybe_exit(EX_DRIZZLEERR);
207
 
  }
208
 
  sbuf.setConnection(destination_connection);
209
 
  std::ostream sout(&sbuf);
210
 
  sout.exceptions(ios_base::badbit);
211
 
 
212
 
  if (path.empty())
213
 
  {
214
 
    sout << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;" << endl;
215
 
    sout << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
216
 
  }
217
 
 
218
 
  if (opt_autocommit)
219
 
    cout << "SET AUTOCOMMIT=0;" << endl;
220
 
 
221
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
222
 
  {
223
 
    try
224
 
    {
225
 
      DrizzleDumpDatabase *database= *i;
226
 
      sout << *database;
227
 
    }
228
 
    catch (std::exception&)
229
 
    {
230
 
      std::cout << _("Error inserting into destination database") << std::endl;
231
 
      if (not ignore_errors)
232
 
        maybe_exit(EX_DRIZZLEERR);
233
 
    }
234
 
  }
235
 
 
236
 
  if (path.empty())
237
 
  {
238
 
    sout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;" << endl;
239
 
    sout << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
240
 
  }
 
428
static char *quote_name(const char *name, char *buff, bool force);
 
429
char check_if_ignore_table(const char *table_name, char *table_type);
 
430
static char *primary_key_fields(const char *table_name);
 
431
 
 
432
/*
 
433
  Print the supplied message if in verbose mode
 
434
 
 
435
  SYNOPSIS
 
436
    verbose_msg()
 
437
    fmt   format specifier
 
438
    ...   variable number of parameters
 
439
*/
 
440
static void verbose_msg(const char *fmt, ...)
 
441
{
 
442
  va_list args;
 
443
 
 
444
 
 
445
  if (!verbose)
 
446
    return;
 
447
 
 
448
  va_start(args, fmt);
 
449
  vfprintf(stderr, fmt, args);
 
450
  va_end(args);
 
451
 
 
452
  return;
241
453
}
242
454
 
243
455
/*
244
456
  exit with message if ferror(file)
245
457
 
246
458
  SYNOPSIS
247
 
  check_io()
248
 
  file        - checked file
 
459
    check_io()
 
460
    file        - checked file
249
461
*/
250
462
 
251
463
static void check_io(FILE *file)
254
466
    die(EX_EOF, _("Got errno %d on write"), errno);
255
467
}
256
468
 
257
 
static void write_header(char *db_name)
258
 
{
259
 
  if ((not opt_compact) and (opt_comments))
260
 
  {
261
 
    cout << "-- drizzledump " << VERSION << " libdrizzle "
262
 
      << drizzle_version() << ", for " << HOST_VENDOR << "-" << HOST_OS
263
 
      << " (" << HOST_CPU << ")" << endl << "--" << endl;
264
 
    cout << "-- Host: " << current_host << "    Database: " << db_name << endl;
265
 
    cout << "-- ------------------------------------------------------" << endl;
266
 
    cout << "-- Server version\t" << db_connection->getServerVersion();
267
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
268
 
      cout << " (MySQL server)";
269
 
    else if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_DRIZZLE_FOUND)
270
 
      cout << " (Drizzle server)";
271
 
    cout << endl << endl;
 
469
static void print_version(void)
 
470
{
 
471
  printf(_("%s  Ver %s Distrib %s, for %s (%s)\n"),my_progname,DUMP_VERSION,
 
472
         drizzleclient_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
 
473
} /* print_version */
 
474
 
 
475
 
 
476
static void short_usage_sub(void)
 
477
{
 
478
  printf(_("Usage: %s [OPTIONS] database [tables]\n"), my_progname);
 
479
  printf(_("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n"),
 
480
         my_progname);
 
481
  printf(_("OR     %s [OPTIONS] --all-databases [OPTIONS]\n"), my_progname);
 
482
}
 
483
 
 
484
 
 
485
static void usage(void)
 
486
{
 
487
  print_version();
 
488
  puts(_("By Igor Romanenko, Monty, Jani & Sinisa"));
 
489
  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"));
 
490
  puts(_("Dumping definition and data DRIZZLE database or table"));
 
491
  short_usage_sub();
 
492
  print_defaults("drizzle",load_default_groups);
 
493
  my_print_help(my_long_options);
 
494
  my_print_variables(my_long_options);
 
495
} /* usage */
 
496
 
 
497
 
 
498
static void short_usage(void)
 
499
{
 
500
  short_usage_sub();
 
501
  printf(_("For more options, use %s --help\n"), my_progname);
 
502
}
 
503
 
 
504
static void write_header(FILE *sql_file, char *db_name)
 
505
{
 
506
  if (opt_xml)
 
507
  {
 
508
    fputs("<?xml version=\"1.0\"?>\n", sql_file);
 
509
    /*
 
510
      Schema reference.  Allows use of xsi:nil for NULL values and
 
511
      xsi:type to define an element's data type.
 
512
    */
 
513
    fputs("<drizzledump ", sql_file);
 
514
    fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
 
515
          sql_file);
 
516
    fputs(">\n", sql_file);
 
517
    check_io(sql_file);
 
518
  }
 
519
  else if (!opt_compact)
 
520
  {
 
521
    if (opt_comments)
 
522
    {
 
523
      fprintf(sql_file,
 
524
              "-- DRIZZLE dump %s  Distrib %s, for %s (%s)\n--\n",
 
525
              DUMP_VERSION, drizzleclient_get_client_info(),
 
526
              SYSTEM_TYPE, MACHINE_TYPE);
 
527
      fprintf(sql_file, "-- Host: %s    Database: %s\n",
 
528
              current_host ? current_host : "localhost", db_name ? db_name :
 
529
              "");
 
530
      fputs("-- ------------------------------------------------------\n",
 
531
            sql_file);
 
532
      fprintf(sql_file, "-- Server version\t%s\n",
 
533
              drizzleclient_get_server_info(&drizzleclient_connection));
 
534
    }
 
535
    if (opt_set_charset)
 
536
      fprintf(sql_file,
 
537
"\nSET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION;"
 
538
"\nSET NAMES %s;\n",default_charset);
 
539
 
 
540
    if (!path)
 
541
    {
 
542
      fprintf(md_result_file,"\
 
543
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;\n\
 
544
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;\n\
 
545
");
 
546
    }
 
547
    check_io(sql_file);
272
548
  }
273
549
} /* write_header */
274
550
 
275
551
 
276
552
static void write_footer(FILE *sql_file)
277
553
{
278
 
  if (! opt_compact)
279
 
  {
 
554
  if (opt_xml)
 
555
  {
 
556
    fputs("</drizzledump>\n", sql_file);
 
557
    check_io(sql_file);
 
558
  }
 
559
  else if (!opt_compact)
 
560
  {
 
561
    if (!path)
 
562
    {
 
563
      fprintf(md_result_file,"\
 
564
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;\n\
 
565
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;\n");
 
566
    }
 
567
    if (opt_set_charset)
 
568
      fprintf(sql_file, "SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION;\n");
280
569
    if (opt_comments)
281
570
    {
282
571
      if (opt_dump_date)
283
572
      {
284
 
        boost::posix_time::ptime time(boost::posix_time::second_clock::local_time());
 
573
        char time_str[20];
 
574
        get_date(time_str, GETDATE_DATE_TIME, 0);
285
575
        fprintf(sql_file, "-- Dump completed on %s\n",
286
 
          boost::posix_time::to_simple_string(time).c_str());
 
576
                time_str);
287
577
      }
288
578
      else
289
579
        fprintf(sql_file, "-- Dump completed\n");
292
582
  }
293
583
} /* write_footer */
294
584
 
295
 
static int get_options(void)
296
 
{
 
585
 
 
586
static void free_table_ent(char *key)
 
587
{
 
588
  free(key);
 
589
}
 
590
 
 
591
 
 
592
static unsigned char* get_table_key(const char *entry, size_t *length, bool)
 
593
{
 
594
  *length= strlen(entry);
 
595
  return (unsigned char*) entry;
 
596
}
 
597
 
 
598
 
 
599
extern "C"
 
600
bool get_one_option(int optid, const struct my_option *, char *argument)
 
601
{
 
602
  char *endchar= NULL;
 
603
  uint64_t temp_drizzle_port= 0;
 
604
 
 
605
  switch (optid) {
 
606
  case 'p':
 
607
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
 
608
    /* if there is an alpha character this is not a valid port */
 
609
    if (strlen(endchar) != 0)
 
610
    {
 
611
      fprintf(stderr, _("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead.\n"));
 
612
      exit(EX_USAGE);
 
613
    }
 
614
    /* If the port number is > 65535 it is not a valid port
 
615
 *        This also helps with potential data loss casting unsigned long to a
 
616
 *               uint32_t. */
 
617
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
 
618
    {
 
619
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
 
620
      exit(EX_USAGE);
 
621
    }
 
622
    else
 
623
    {
 
624
      opt_drizzle_port= (uint32_t) temp_drizzle_port;
 
625
    }
 
626
    break;
 
627
  case 'P':
 
628
    if (argument)
 
629
    {
 
630
      char *start= argument;
 
631
      if (opt_password)
 
632
        free(opt_password);
 
633
      opt_password= strdup(argument);
 
634
      if (opt_password == NULL)
 
635
      {
 
636
        fprintf(stderr, _("Memory allocation error while copying password. "
 
637
                        "Aborting.\n"));
 
638
        exit(ENOMEM);
 
639
      }
 
640
      while (*argument)
 
641
      {
 
642
        /* Overwriting password with 'x' */
 
643
        *argument++= 'x';
 
644
      }
 
645
      if (*start)
 
646
      {
 
647
        /* Cut length of argument */
 
648
        start[1]= 0;
 
649
      }
 
650
      tty_password= 0;
 
651
    }
 
652
    else
 
653
    {
 
654
      tty_password= 1;
 
655
    }
 
656
    break;
 
657
  case 'r':
 
658
    if (!(md_result_file= my_fopen(argument, O_WRONLY,
 
659
                                    MYF(MY_WME))))
 
660
      exit(1);
 
661
    break;
 
662
  case 'N':
 
663
    opt_set_charset= 0;
 
664
    break;
 
665
  case 'T':
 
666
    opt_disable_keys=0;
 
667
 
 
668
    if (strlen(argument) >= FN_REFLEN)
 
669
    {
 
670
      /*
 
671
        This check is made because the some the file functions below
 
672
        have FN_REFLEN sized stack allocated buffers and will cause
 
673
        a crash even if the input destination buffer is large enough
 
674
        to hold the output.
 
675
      */
 
676
      die(EX_USAGE, _("Input filename too long: %s"), argument);
 
677
    }
 
678
 
 
679
    break;
 
680
  case 'V': print_version(); exit(0);
 
681
  case 'X':
 
682
    opt_xml= 1;
 
683
    extended_insert= opt_drop= opt_lock=
 
684
      opt_disable_keys= opt_autocommit= opt_create_db= 0;
 
685
    break;
 
686
  case 'I':
 
687
  case '?':
 
688
    usage();
 
689
    exit(0);
 
690
  case (int) OPT_MASTER_DATA:
 
691
    if (!argument) /* work like in old versions */
 
692
      opt_master_data= DRIZZLE_OPT_MASTER_DATA_EFFECTIVE_SQL;
 
693
    break;
 
694
  case (int) OPT_DRIZZLEDUMP_SLAVE_DATA:
 
695
    if (!argument) /* work like in old versions */
 
696
      opt_slave_data= DRIZZLE_OPT_SLAVE_DATA_EFFECTIVE_SQL;
 
697
    break;
 
698
  case (int) OPT_OPTIMIZE:
 
699
    extended_insert= opt_drop= opt_lock= quick= create_options=
 
700
      opt_disable_keys= lock_tables= opt_set_charset= 1;
 
701
    break;
 
702
  case (int) OPT_SKIP_OPTIMIZATION:
 
703
    extended_insert= opt_drop= opt_lock= quick= create_options=
 
704
      opt_disable_keys= lock_tables= opt_set_charset= 0;
 
705
    break;
 
706
  case (int) OPT_COMPACT:
 
707
  if (opt_compact)
 
708
  {
 
709
    opt_comments= opt_drop= opt_disable_keys= opt_lock= 0;
 
710
    opt_set_charset= 0;
 
711
  }
 
712
  case (int) OPT_TABLES:
 
713
    opt_databases=0;
 
714
    break;
 
715
  case (int) OPT_IGNORE_TABLE:
 
716
  {
 
717
    if (!strchr(argument, '.'))
 
718
    {
 
719
      fprintf(stderr, _("Illegal use of option --ignore-table=<database>.<table>\n"));
 
720
      exit(1);
 
721
    }
 
722
    char * tmpptr= strdup(argument);
 
723
    if (!(tmpptr) || my_hash_insert(&ignore_table, (unsigned char*)tmpptr))
 
724
      exit(EX_EOM);
 
725
    break;
 
726
  }
 
727
  case (int) OPT_COMPATIBLE:
 
728
    {
 
729
      char buff[255];
 
730
      char *end= compatible_mode_normal_str;
 
731
      uint32_t i;
 
732
      uint32_t mode;
 
733
      uint32_t error_len;
 
734
 
 
735
      opt_quoted= 1;
 
736
      opt_set_charset= 0;
 
737
      opt_compatible_mode_str= argument;
 
738
      opt_compatible_mode= find_set(&compatible_mode_typelib,
 
739
                                    argument, strlen(argument),
 
740
                                    &err_ptr, &error_len);
 
741
      if (error_len)
 
742
      {
 
743
        strncpy(buff, err_ptr, min((uint32_t)sizeof(buff), error_len));
 
744
        fprintf(stderr, _("Invalid mode to --compatible: %s\n"), buff);
 
745
        exit(1);
 
746
      }
 
747
      mode= opt_compatible_mode;
 
748
      for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++)
 
749
      {
 
750
        if (mode & 1)
 
751
        {
 
752
          uint32_t len = strlen(compatible_mode_names[i]);
 
753
          end= strcpy(end, compatible_mode_names[i]) + len;
 
754
          end= strcpy(end, ",")+1;
 
755
        }
 
756
      }
 
757
      if (end!=compatible_mode_normal_str)
 
758
        end[-1]= 0;
 
759
      /*
 
760
        Set charset to the default compiled value if it hasn't
 
761
        been reset yet by --default-character-set=xxx.
 
762
      */
 
763
      if (default_charset == drizzle_universal_client_charset)
 
764
        default_charset= (char*) DRIZZLE_DEFAULT_CHARSET_NAME;
 
765
      break;
 
766
    }
 
767
  }
 
768
  return 0;
 
769
}
 
770
 
 
771
static int get_options(int *argc, char ***argv)
 
772
{
 
773
  int ho_error;
 
774
  const DRIZZLE_PARAMETERS *drizzle_params= drizzleclient_get_parameters();
 
775
 
 
776
  opt_max_allowed_packet= *drizzle_params->p_max_allowed_packet;
 
777
  opt_net_buffer_length= *drizzle_params->p_net_buffer_length;
 
778
 
 
779
  md_result_file= stdout;
 
780
  load_defaults("drizzle",load_default_groups,argc,argv);
 
781
  defaults_argv= *argv;
 
782
 
 
783
  if (hash_init(&ignore_table, charset_info, 16, 0, 0,
 
784
                (hash_get_key) get_table_key,
 
785
                (hash_free_key) free_table_ent, 0))
 
786
    return(EX_EOM);
 
787
 
 
788
  if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
 
789
    return(ho_error);
 
790
 
 
791
  *drizzle_params->p_max_allowed_packet= opt_max_allowed_packet;
 
792
  *drizzle_params->p_net_buffer_length= opt_net_buffer_length;
 
793
  if (debug_info_flag)
 
794
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
 
795
  if (debug_check_flag)
 
796
    my_end_arg= MY_CHECK_ERROR;
 
797
 
 
798
  if (opt_delayed)
 
799
    opt_lock=0;                         /* Can't have lock with delayed */
 
800
  if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
 
801
                fields_terminated))
 
802
  {
 
803
    fprintf(stderr,
 
804
            _("%s: You must use option --tab with --fields-...\n"), my_progname);
 
805
    return(EX_USAGE);
 
806
  }
 
807
 
 
808
  /* We don't delete master logs if slave data option */
 
809
  if (opt_slave_data)
 
810
  {
 
811
    opt_lock_all_tables= !opt_single_transaction;
 
812
    opt_master_data= 0;
 
813
    opt_delete_master_logs= 0;
 
814
  }
 
815
 
 
816
  /* Ensure consistency of the set of binlog & locking options */
 
817
  if (opt_delete_master_logs && !opt_master_data)
 
818
    opt_master_data= DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL;
297
819
  if (opt_single_transaction && opt_lock_all_tables)
298
820
  {
299
821
    fprintf(stderr, _("%s: You can't use --single-transaction and "
300
 
                      "--lock-all-tables at the same time.\n"), progname.c_str());
301
 
    return(EX_USAGE);
302
 
  }
303
 
  if ((opt_databases || opt_alldbs) && ! path.empty())
 
822
            "--lock-all-tables at the same time.\n"), my_progname);
 
823
    return(EX_USAGE);
 
824
  }
 
825
  if (opt_master_data)
 
826
  {
 
827
    opt_lock_all_tables= !opt_single_transaction;
 
828
    opt_slave_data= 0;
 
829
  }
 
830
  if (opt_single_transaction || opt_lock_all_tables)
 
831
    lock_tables= 0;
 
832
  if (enclosed && opt_enclosed)
 
833
  {
 
834
    fprintf(stderr, _("%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n"), my_progname);
 
835
    return(EX_USAGE);
 
836
  }
 
837
  if ((opt_databases || opt_alldbs) && path)
304
838
  {
305
839
    fprintf(stderr,
306
840
            _("%s: --databases or --all-databases can't be used with --tab.\n"),
307
 
            progname.c_str());
 
841
            my_progname);
308
842
    return(EX_USAGE);
309
843
  }
310
 
 
 
844
  if (strcmp(default_charset, charset_info->csname) &&
 
845
      !(charset_info= get_charset_by_csname(default_charset, MY_CS_PRIMARY)))
 
846
    exit(1);
 
847
  if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
 
848
  {
 
849
    short_usage();
 
850
    return EX_USAGE;
 
851
  }
311
852
  if (tty_password)
312
 
    opt_password=client_get_tty_password(NULL);
 
853
    opt_password=drizzleclient_get_tty_password(NULL);
313
854
  return(0);
314
855
} /* get_options */
315
856
 
316
857
 
317
858
/*
 
859
** DB_error -- prints DRIZZLE error message and exits the program.
 
860
*/
 
861
static void DB_error(DRIZZLE *drizzle_arg, const char *when)
 
862
{
 
863
 
 
864
  maybe_die(EX_DRIZZLEERR, _("Got error: %d: %s %s"),
 
865
          drizzleclient_errno(drizzle_arg), drizzleclient_error(drizzle_arg), when);
 
866
  return;
 
867
}
 
868
 
 
869
 
 
870
 
 
871
/*
318
872
  Prints out an error message and kills the process.
319
873
 
320
874
  SYNOPSIS
321
 
  die()
322
 
  error_num   - process return value
323
 
  fmt_reason  - a format string for use by vsnprintf.
324
 
  ...         - variable arguments for above fmt_reason string
 
875
    die()
 
876
    error_num   - process return value
 
877
    fmt_reason  - a format string for use by vsnprintf.
 
878
    ...         - variable arguments for above fmt_reason string
325
879
 
326
880
  DESCRIPTION
327
 
  This call prints out the formatted error message to stderr and then
328
 
  terminates the process.
 
881
    This call prints out the formatted error message to stderr and then
 
882
    terminates the process.
329
883
*/
330
884
static void die(int error_num, const char* fmt_reason, ...)
331
885
{
335
889
  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
336
890
  va_end(args);
337
891
 
338
 
  fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
 
892
  fprintf(stderr, "%s: %s\n", my_progname, buffer);
339
893
  fflush(stderr);
340
894
 
341
895
  ignore_errors= 0; /* force the exit */
342
896
  maybe_exit(error_num);
343
897
}
344
898
 
 
899
 
 
900
/*
 
901
  Prints out an error message and maybe kills the process.
 
902
 
 
903
  SYNOPSIS
 
904
    maybe_die()
 
905
    error_num   - process return value
 
906
    fmt_reason  - a format string for use by vsnprintf.
 
907
    ...         - variable arguments for above fmt_reason string
 
908
 
 
909
  DESCRIPTION
 
910
    This call prints out the formatted error message to stderr and then
 
911
    terminates the process, unless the --force command line option is used.
 
912
 
 
913
    This call should be used for non-fatal errors (such as database
 
914
    errors) that the code may still be able to continue to the next unit
 
915
    of work.
 
916
 
 
917
*/
 
918
static void maybe_die(int error_num, const char* fmt_reason, ...)
 
919
{
 
920
  char buffer[1000];
 
921
  va_list args;
 
922
  va_start(args,fmt_reason);
 
923
  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
 
924
  va_end(args);
 
925
 
 
926
  fprintf(stderr, "%s: %s\n", my_progname, buffer);
 
927
  fflush(stderr);
 
928
 
 
929
  maybe_exit(error_num);
 
930
}
 
931
 
 
932
 
 
933
 
 
934
/*
 
935
  Sends a query to server, optionally reads result, prints error message if
 
936
  some.
 
937
 
 
938
  SYNOPSIS
 
939
    drizzleclient_query_with_error_report()
 
940
    drizzle_con       connection to use
 
941
    res             if non zero, result will be put there with
 
942
                    drizzleclient_store_result()
 
943
    query           query to send to server
 
944
 
 
945
  RETURN VALUES
 
946
    0               query sending and (if res!=0) result reading went ok
 
947
    1               error
 
948
*/
 
949
 
 
950
static int drizzleclient_query_with_error_report(DRIZZLE *drizzle_con, DRIZZLE_RES **res,
 
951
                                         const char *query)
 
952
{
 
953
  if (drizzleclient_query(drizzle_con, query) ||
 
954
      (res && !((*res)= drizzleclient_store_result(drizzle_con))))
 
955
  {
 
956
    maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
957
            query, drizzleclient_error(drizzle_con), drizzleclient_errno(drizzle_con));
 
958
    return 1;
 
959
  }
 
960
  return 0;
 
961
}
 
962
 
 
963
/*
 
964
  Open a new .sql file to dump the table or view into
 
965
 
 
966
  SYNOPSIS
 
967
    open_sql_file_for_table
 
968
    name      name of the table or view
 
969
 
 
970
  RETURN VALUES
 
971
    0        Failed to open file
 
972
    > 0      Handle of the open file
 
973
*/
 
974
static FILE* open_sql_file_for_table(const char* table)
 
975
{
 
976
  FILE* res;
 
977
  char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
978
  convert_dirname(tmp_path,path,NULL);
 
979
  res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
 
980
                O_WRONLY, MYF(MY_WME));
 
981
  return res;
 
982
}
 
983
 
 
984
 
345
985
static void free_resources(void)
346
986
{
347
987
  if (md_result_file && md_result_file != stdout)
348
 
    fclose(md_result_file);
349
 
  opt_password.erase();
 
988
    my_fclose(md_result_file, MYF(0));
 
989
  free(opt_password);
 
990
  if (hash_inited(&ignore_table))
 
991
    hash_free(&ignore_table);
 
992
  if (defaults_argv)
 
993
    free_defaults(defaults_argv);
 
994
  my_end(my_end_arg);
350
995
}
351
996
 
352
997
 
353
 
void maybe_exit(int error)
 
998
static void maybe_exit(int error)
354
999
{
355
1000
  if (!first_error)
356
1001
    first_error= error;
357
1002
  if (ignore_errors)
358
1003
    return;
359
 
  delete db_connection;
360
 
  delete destination_connection;
 
1004
  if (drizzle)
 
1005
    drizzleclient_close(drizzle);
361
1006
  free_resources();
362
1007
  exit(error);
363
1008
}
364
1009
 
 
1010
 
 
1011
/*
 
1012
  db_connect -- connects to the host and selects DB.
 
1013
*/
 
1014
 
 
1015
static int connect_to_db(char *host, char *user,char *passwd)
 
1016
{
 
1017
  verbose_msg(_("-- Connecting to %s...\n"), host ? host : "localhost");
 
1018
  drizzleclient_create(&drizzleclient_connection);
 
1019
  if (opt_compress)
 
1020
    drizzleclient_options(&drizzleclient_connection,DRIZZLE_OPT_COMPRESS,NULL);
 
1021
  if (!(drizzle= drizzleclient_connect(&drizzleclient_connection,host,user,passwd,
 
1022
                                  NULL,opt_drizzle_port, NULL,
 
1023
                                  0)))
 
1024
  {
 
1025
    DB_error(&drizzleclient_connection, "when trying to connect");
 
1026
    return(1);
 
1027
  }
 
1028
 
 
1029
  return(0);
 
1030
} /* connect_to_db */
 
1031
 
 
1032
 
 
1033
/*
 
1034
** dbDisconnect -- disconnects from the host.
 
1035
*/
 
1036
static void dbDisconnect(char *host)
 
1037
{
 
1038
  verbose_msg(_("-- Disconnecting from %s...\n"), host ? host : "localhost");
 
1039
  drizzleclient_close(drizzle);
 
1040
} /* dbDisconnect */
 
1041
 
 
1042
 
 
1043
static void unescape(FILE *file,char *pos,uint32_t length)
 
1044
{
 
1045
  char *tmp;
 
1046
 
 
1047
  if (!(tmp=(char*) malloc(length*2+1)))
 
1048
    die(EX_DRIZZLEERR, _("Couldn't allocate memory"));
 
1049
 
 
1050
  drizzleclient_escape_string(tmp, pos, length);
 
1051
  fputc('\'', file);
 
1052
  fputs(tmp, file);
 
1053
  fputc('\'', file);
 
1054
  check_io(file);
 
1055
  free(tmp);
 
1056
  return;
 
1057
} /* unescape */
 
1058
 
 
1059
 
 
1060
static bool test_if_special_chars(const char *str)
 
1061
{
 
1062
  for ( ; *str ; str++)
 
1063
    if (!my_isvar(charset_info,*str) && *str != '$')
 
1064
      return 1;
 
1065
  return 0;
 
1066
} /* test_if_special_chars */
 
1067
 
 
1068
 
 
1069
 
 
1070
/*
 
1071
  quote_name(name, buff, force)
 
1072
 
 
1073
  Quotes char string, taking into account compatible mode
 
1074
 
 
1075
  Args
 
1076
 
 
1077
  name                 Unquoted string containing that which will be quoted
 
1078
  buff                 The buffer that contains the quoted value, also returned
 
1079
  force                Flag to make it ignore 'test_if_special_chars'
 
1080
 
 
1081
  Returns
 
1082
 
 
1083
  buff                 quoted string
 
1084
 
 
1085
*/
 
1086
static char *quote_name(const char *name, char *buff, bool force)
 
1087
{
 
1088
  char *to= buff;
 
1089
  char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';
 
1090
 
 
1091
  if (!force && !opt_quoted && !test_if_special_chars(name))
 
1092
    return (char*) name;
 
1093
  *to++= qtype;
 
1094
  while (*name)
 
1095
  {
 
1096
    if (*name == qtype)
 
1097
      *to++= qtype;
 
1098
    *to++= *name++;
 
1099
  }
 
1100
  to[0]= qtype;
 
1101
  to[1]= 0;
 
1102
  return buff;
 
1103
} /* quote_name */
 
1104
 
 
1105
 
 
1106
/*
 
1107
  Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
 
1108
 
 
1109
  SYNOPSIS
 
1110
    quote_for_like()
 
1111
    name     name of the table
 
1112
    buff     quoted name of the table
 
1113
 
 
1114
  DESCRIPTION
 
1115
    Quote \, _, ' and % characters
 
1116
 
 
1117
    Note: Because DRIZZLE uses the C escape syntax in strings
 
1118
    (for example, '\n' to represent newline), you must double
 
1119
    any '\' that you use in your LIKE  strings. For example, to
 
1120
    search for '\n', specify it as '\\n'. To search for '\', specify
 
1121
    it as '\\\\' (the backslashes are stripped once by the parser
 
1122
    and another time when the pattern match is done, leaving a
 
1123
    single backslash to be matched).
 
1124
 
 
1125
    Example: "t\1" => "t\\\\1"
 
1126
 
 
1127
*/
 
1128
static char *quote_for_like(const char *name, char *buff)
 
1129
{
 
1130
  char *to= buff;
 
1131
  *to++= '\'';
 
1132
  while (*name)
 
1133
  {
 
1134
    if (*name == '\\')
 
1135
    {
 
1136
      *to++='\\';
 
1137
      *to++='\\';
 
1138
      *to++='\\';
 
1139
    }
 
1140
    else if (*name == '\'' || *name == '_'  || *name == '%')
 
1141
      *to++= '\\';
 
1142
    *to++= *name++;
 
1143
  }
 
1144
  to[0]= '\'';
 
1145
  to[1]= 0;
 
1146
  return buff;
 
1147
}
 
1148
 
 
1149
 
 
1150
/*
 
1151
  Quote and print a string.
 
1152
 
 
1153
  SYNOPSIS
 
1154
    print_quoted_xml()
 
1155
    xml_file    - output file
 
1156
    str         - string to print
 
1157
    len         - its length
 
1158
 
 
1159
  DESCRIPTION
 
1160
    Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
 
1161
*/
 
1162
 
 
1163
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
 
1164
{
 
1165
  const char *end;
 
1166
 
 
1167
  for (end= str + len; str != end; str++)
 
1168
  {
 
1169
    switch (*str) {
 
1170
    case '<':
 
1171
      fputs("&lt;", xml_file);
 
1172
      break;
 
1173
    case '>':
 
1174
      fputs("&gt;", xml_file);
 
1175
      break;
 
1176
    case '&':
 
1177
      fputs("&amp;", xml_file);
 
1178
      break;
 
1179
    case '\"':
 
1180
      fputs("&quot;", xml_file);
 
1181
      break;
 
1182
    default:
 
1183
      fputc(*str, xml_file);
 
1184
      break;
 
1185
    }
 
1186
  }
 
1187
  check_io(xml_file);
 
1188
}
 
1189
 
 
1190
 
 
1191
/*
 
1192
  Print xml tag. Optionally add attribute(s).
 
1193
 
 
1194
  SYNOPSIS
 
1195
    print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
 
1196
                    ..., attribute_name_n, attribute_value_n, NULL)
 
1197
    xml_file              - output file
 
1198
    sbeg                  - line beginning
 
1199
    line_end              - line ending
 
1200
    tag_name              - XML tag name.
 
1201
    first_attribute_name  - tag and first attribute
 
1202
    first_attribute_value - (Implied) value of first attribute
 
1203
    attribute_name_n      - attribute n
 
1204
    attribute_value_n     - value of attribute n
 
1205
 
 
1206
  DESCRIPTION
 
1207
    Print XML tag with any number of attribute="value" pairs to the xml_file.
 
1208
 
 
1209
    Format is:
 
1210
      sbeg<tag_name first_attribute_name="first_attribute_value" ...
 
1211
      attribute_name_n="attribute_value_n">send
 
1212
  NOTE
 
1213
    Additional arguments must be present in attribute/value pairs.
 
1214
    The last argument should be the null character pointer.
 
1215
    All attribute_value arguments MUST be NULL terminated strings.
 
1216
    All attribute_value arguments will be quoted before output.
 
1217
*/
 
1218
 
 
1219
static void print_xml_tag(FILE * xml_file, const char* sbeg,
 
1220
                          const char* line_end,
 
1221
                          const char* tag_name,
 
1222
                          const char* first_attribute_name, ...)
 
1223
{
 
1224
  va_list arg_list;
 
1225
  const char *attribute_name, *attribute_value;
 
1226
 
 
1227
  fputs(sbeg, xml_file);
 
1228
  fputc('<', xml_file);
 
1229
  fputs(tag_name, xml_file);
 
1230
 
 
1231
  va_start(arg_list, first_attribute_name);
 
1232
  attribute_name= first_attribute_name;
 
1233
  while (attribute_name != NULL)
 
1234
  {
 
1235
    attribute_value= va_arg(arg_list, char *);
 
1236
    assert(attribute_value != NULL);
 
1237
 
 
1238
    fputc(' ', xml_file);
 
1239
    fputs(attribute_name, xml_file);
 
1240
    fputc('\"', xml_file);
 
1241
 
 
1242
    print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
 
1243
    fputc('\"', xml_file);
 
1244
 
 
1245
    attribute_name= va_arg(arg_list, char *);
 
1246
  }
 
1247
  va_end(arg_list);
 
1248
 
 
1249
  fputc('>', xml_file);
 
1250
  fputs(line_end, xml_file);
 
1251
  check_io(xml_file);
 
1252
}
 
1253
 
 
1254
 
 
1255
/*
 
1256
  Print xml tag with for a field that is null
 
1257
 
 
1258
  SYNOPSIS
 
1259
    print_xml_null_tag()
 
1260
    xml_file    - output file
 
1261
    sbeg        - line beginning
 
1262
    stag_atr    - tag and attribute
 
1263
    sval        - value of attribute
 
1264
    line_end        - line ending
 
1265
 
 
1266
  DESCRIPTION
 
1267
    Print tag with one attribute to the xml_file. Format is:
 
1268
      <stag_atr="sval" xsi:nil="true"/>
 
1269
  NOTE
 
1270
    sval MUST be a NULL terminated string.
 
1271
    sval string will be qouted before output.
 
1272
*/
 
1273
 
 
1274
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
 
1275
                               const char* stag_atr, const char* sval,
 
1276
                               const char* line_end)
 
1277
{
 
1278
  fputs(sbeg, xml_file);
 
1279
  fputs("<", xml_file);
 
1280
  fputs(stag_atr, xml_file);
 
1281
  fputs("\"", xml_file);
 
1282
  print_quoted_xml(xml_file, sval, strlen(sval));
 
1283
  fputs("\" xsi:nil=\"true\" />", xml_file);
 
1284
  fputs(line_end, xml_file);
 
1285
  check_io(xml_file);
 
1286
}
 
1287
 
 
1288
 
 
1289
/*
 
1290
  Print xml tag with many attributes.
 
1291
 
 
1292
  SYNOPSIS
 
1293
    print_xml_row()
 
1294
    xml_file    - output file
 
1295
    row_name    - xml tag name
 
1296
    tableRes    - query result
 
1297
    row         - result row
 
1298
 
 
1299
  DESCRIPTION
 
1300
    Print tag with many attribute to the xml_file. Format is:
 
1301
      \t\t<row_name Atr1="Val1" Atr2="Val2"... />
 
1302
  NOTE
 
1303
    All atributes and values will be quoted before output.
 
1304
*/
 
1305
 
 
1306
static void print_xml_row(FILE *xml_file, const char *row_name,
 
1307
                          DRIZZLE_RES *tableRes, DRIZZLE_ROW *row)
 
1308
{
 
1309
  uint32_t i;
 
1310
  DRIZZLE_FIELD *field;
 
1311
  uint32_t *lengths= drizzleclient_fetch_lengths(tableRes);
 
1312
 
 
1313
  fprintf(xml_file, "\t\t<%s", row_name);
 
1314
  check_io(xml_file);
 
1315
  drizzleclient_field_seek(tableRes, 0);
 
1316
  for (i= 0; (field= drizzleclient_fetch_field(tableRes)); i++)
 
1317
  {
 
1318
    if ((*row)[i])
 
1319
    {
 
1320
      fputc(' ', xml_file);
 
1321
      print_quoted_xml(xml_file, field->name, field->name_length);
 
1322
      fputs("=\"", xml_file);
 
1323
      print_quoted_xml(xml_file, (*row)[i], lengths[i]);
 
1324
      fputc('"', xml_file);
 
1325
      check_io(xml_file);
 
1326
    }
 
1327
  }
 
1328
  fputs(" />\n", xml_file);
 
1329
  check_io(xml_file);
 
1330
}
 
1331
 
 
1332
 
 
1333
/*
 
1334
  Print hex value for blob data.
 
1335
 
 
1336
  SYNOPSIS
 
1337
    print_blob_as_hex()
 
1338
    output_file         - output file
 
1339
    str                 - string to print
 
1340
    len                 - its length
 
1341
 
 
1342
  DESCRIPTION
 
1343
    Print hex value for blob data.
 
1344
*/
 
1345
 
 
1346
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
 
1347
{
 
1348
    /* sakaik got the idea to to provide blob's in hex notation. */
 
1349
    const char *ptr= str, *end= ptr + len;
 
1350
    for (; ptr < end ; ptr++)
 
1351
      fprintf(output_file, "%02X", *((unsigned char *)ptr));
 
1352
    check_io(output_file);
 
1353
}
 
1354
 
 
1355
/*
 
1356
  get_table_structure -- retrievs database structure, prints out corresponding
 
1357
  CREATE statement and fills out insert_pat if the table is the type we will
 
1358
  be dumping.
 
1359
 
 
1360
  ARGS
 
1361
    table       - table name
 
1362
    db          - db name
 
1363
    table_type  - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
 
1364
    ignore_flag - what we must particularly ignore - see IGNORE_ defines above
 
1365
    num_fields  - number of fields in the table
 
1366
 
 
1367
  RETURN
 
1368
    true if success, false if error
 
1369
*/
 
1370
 
 
1371
static bool get_table_structure(char *table, char *db, char *table_type,
 
1372
                                char *ignore_flag, uint64_t *num_fields)
 
1373
{
 
1374
  bool    init=0, delayed, write_data, complete_insert;
 
1375
  char       *result_table, *opt_quoted_table;
 
1376
  const char *insert_option;
 
1377
  char       name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
 
1378
  char       table_buff2[NAME_LEN*2+3], query_buff[QUERY_LENGTH];
 
1379
  FILE       *sql_file= md_result_file;
 
1380
  DRIZZLE_RES  *result;
 
1381
  DRIZZLE_ROW  row;
 
1382
 
 
1383
  *ignore_flag= check_if_ignore_table(table, table_type);
 
1384
 
 
1385
  delayed= opt_delayed;
 
1386
  if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
 
1387
  {
 
1388
    delayed= 0;
 
1389
    verbose_msg(_("-- Warning: Unable to use delayed inserts for table '%s' "
 
1390
                "because it's of type %s\n"), table, table_type);
 
1391
  }
 
1392
 
 
1393
  complete_insert= 0;
 
1394
  if ((write_data= !(*ignore_flag & IGNORE_DATA)))
 
1395
  {
 
1396
    complete_insert= opt_complete_insert;
 
1397
    insert_pat.clear();
 
1398
  }
 
1399
 
 
1400
  insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
 
1401
                  delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
 
1402
 
 
1403
  verbose_msg(_("-- Retrieving table structure for table %s...\n"), table);
 
1404
 
 
1405
  result_table=     quote_name(table, table_buff, 1);
 
1406
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
1407
 
 
1408
  if (opt_order_by_primary)
 
1409
  {
 
1410
    free(order_by);
 
1411
    order_by= primary_key_fields(result_table);
 
1412
  }
 
1413
 
 
1414
  if (!opt_xml)
 
1415
  {
 
1416
    /* using SHOW CREATE statement */
 
1417
    if (!opt_no_create_info)
 
1418
    {
 
1419
      /* Make an sql-file, if path was given iow. option -T was given */
 
1420
      char buff[20+FN_REFLEN];
 
1421
      const DRIZZLE_FIELD *field;
 
1422
 
 
1423
      snprintf(buff, sizeof(buff), "show create table %s", result_table);
 
1424
 
 
1425
      if (drizzleclient_query_with_error_report(drizzle, &result, buff))
 
1426
        return false;
 
1427
 
 
1428
      if (path)
 
1429
      {
 
1430
        if (!(sql_file= open_sql_file_for_table(table)))
 
1431
          return false;
 
1432
 
 
1433
        write_header(sql_file, db);
 
1434
      }
 
1435
      if (!opt_xml && opt_comments)
 
1436
      {
 
1437
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
1438
                result_table);
 
1439
        check_io(sql_file);
 
1440
      }
 
1441
      if (opt_drop)
 
1442
      {
 
1443
      /*
 
1444
        Even if the "table" is a view, we do a DROP TABLE here.
 
1445
       */
 
1446
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
 
1447
        check_io(sql_file);
 
1448
      }
 
1449
 
 
1450
      field= drizzleclient_fetch_field_direct(result, 0);
 
1451
 
 
1452
      row= drizzleclient_fetch_row(result);
 
1453
 
 
1454
      fprintf(sql_file, "%s;\n", row[1]);
 
1455
 
 
1456
      check_io(sql_file);
 
1457
      drizzleclient_free_result(result);
 
1458
    }
 
1459
    snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
1460
             result_table);
 
1461
    if (drizzleclient_query_with_error_report(drizzle, &result, query_buff))
 
1462
    {
 
1463
      if (path)
 
1464
        my_fclose(sql_file, MYF(MY_WME));
 
1465
      return false;
 
1466
    }
 
1467
 
 
1468
    /*
 
1469
      If write_data is true, then we build up insert statements for
 
1470
      the table's data. Note: in subsequent lines of code, this test
 
1471
      will have to be performed each time we are appending to
 
1472
      insert_pat.
 
1473
    */
 
1474
    if (write_data)
 
1475
    {
 
1476
      if (opt_replace_into)
 
1477
        insert_pat.append("REPLACE ");
 
1478
      else
 
1479
        insert_pat.append("INSERT ");
 
1480
      insert_pat.append(insert_option);
 
1481
      insert_pat.append("INTO ");
 
1482
      insert_pat.append(opt_quoted_table);
 
1483
      if (complete_insert)
 
1484
      {
 
1485
        insert_pat.append(" (");
 
1486
      }
 
1487
      else
 
1488
      {
 
1489
        insert_pat.append(" VALUES ");
 
1490
        if (!extended_insert)
 
1491
          insert_pat.append("(");
 
1492
      }
 
1493
    }
 
1494
 
 
1495
    while ((row= drizzleclient_fetch_row(result)))
 
1496
    {
 
1497
      if (complete_insert)
 
1498
      {
 
1499
        if (init)
 
1500
        {
 
1501
          insert_pat.append(", ");
 
1502
        }
 
1503
        init=1;
 
1504
        insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
1505
      }
 
1506
    }
 
1507
    *num_fields= drizzleclient_num_rows(result);
 
1508
    drizzleclient_free_result(result);
 
1509
  }
 
1510
  else
 
1511
  {
 
1512
    verbose_msg(_("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n"),
 
1513
                my_progname, drizzleclient_error(drizzle));
 
1514
 
 
1515
    snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
1516
             result_table);
 
1517
    if (drizzleclient_query_with_error_report(drizzle, &result, query_buff))
 
1518
      return false;
 
1519
 
 
1520
    /* Make an sql-file, if path was given iow. option -T was given */
 
1521
    if (!opt_no_create_info)
 
1522
    {
 
1523
      if (path)
 
1524
      {
 
1525
        if (!(sql_file= open_sql_file_for_table(table)))
 
1526
          return false;
 
1527
        write_header(sql_file, db);
 
1528
      }
 
1529
      if (!opt_xml && opt_comments)
 
1530
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
1531
                result_table);
 
1532
      if (opt_drop)
 
1533
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
 
1534
      if (!opt_xml)
 
1535
        fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
 
1536
      else
 
1537
        print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
 
1538
                NULL);
 
1539
      check_io(sql_file);
 
1540
    }
 
1541
 
 
1542
    if (write_data)
 
1543
    {
 
1544
      if (opt_replace_into)
 
1545
        insert_pat.append("REPLACE ");
 
1546
      else
 
1547
        insert_pat.append("INSERT ");
 
1548
      insert_pat.append(insert_option);
 
1549
      insert_pat.append("INTO ");
 
1550
      insert_pat.append(result_table);
 
1551
      if (complete_insert)
 
1552
        insert_pat.append(" (");
 
1553
      else
 
1554
      {
 
1555
        insert_pat.append(" VALUES ");
 
1556
        if (!extended_insert)
 
1557
          insert_pat.append("(");
 
1558
      }
 
1559
    }
 
1560
 
 
1561
    while ((row= drizzleclient_fetch_row(result)))
 
1562
    {
 
1563
      uint32_t *lengths= drizzleclient_fetch_lengths(result);
 
1564
      if (init)
 
1565
      {
 
1566
        if (!opt_xml && !opt_no_create_info)
 
1567
        {
 
1568
          fputs(",\n",sql_file);
 
1569
          check_io(sql_file);
 
1570
        }
 
1571
        if (complete_insert)
 
1572
          insert_pat.append(", ");
 
1573
      }
 
1574
      init=1;
 
1575
      if (complete_insert)
 
1576
        insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
1577
      if (!opt_no_create_info)
 
1578
      {
 
1579
        if (opt_xml)
 
1580
        {
 
1581
          print_xml_row(sql_file, "field", result, &row);
 
1582
          continue;
 
1583
        }
 
1584
 
 
1585
        if (opt_keywords)
 
1586
          fprintf(sql_file, "  %s.%s %s", result_table,
 
1587
                  quote_name(row[SHOW_FIELDNAME],name_buff, 0),
 
1588
                  row[SHOW_TYPE]);
 
1589
        else
 
1590
          fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
 
1591
                                                  name_buff, 0),
 
1592
                  row[SHOW_TYPE]);
 
1593
        if (row[SHOW_DEFAULT])
 
1594
        {
 
1595
          fputs(" DEFAULT ", sql_file);
 
1596
          unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
 
1597
        }
 
1598
        if (!row[SHOW_NULL][0])
 
1599
          fputs(" NOT NULL", sql_file);
 
1600
        if (row[SHOW_EXTRA][0])
 
1601
          fprintf(sql_file, " %s",row[SHOW_EXTRA]);
 
1602
        check_io(sql_file);
 
1603
      }
 
1604
    }
 
1605
    *num_fields= drizzleclient_num_rows(result);
 
1606
    drizzleclient_free_result(result);
 
1607
    if (!opt_no_create_info)
 
1608
    {
 
1609
      /* Make an sql-file, if path was given iow. option -T was given */
 
1610
      char buff[20+FN_REFLEN];
 
1611
      uint32_t keynr,primary_key;
 
1612
      snprintf(buff, sizeof(buff), "show keys from %s", result_table);
 
1613
      if (drizzleclient_query_with_error_report(drizzle, &result, buff))
 
1614
      {
 
1615
        if (drizzleclient_errno(drizzle) == ER_WRONG_OBJECT)
 
1616
        {
 
1617
          /* it is VIEW */
 
1618
          fputs("\t\t<options Comment=\"view\" />\n", sql_file);
 
1619
          goto continue_xml;
 
1620
        }
 
1621
        fprintf(stderr, _("%s: Can't get keys for table %s (%s)\n"),
 
1622
                my_progname, result_table, drizzleclient_error(drizzle));
 
1623
        if (path)
 
1624
          my_fclose(sql_file, MYF(MY_WME));
 
1625
        return false;
 
1626
      }
 
1627
 
 
1628
      /* Find first which key is primary key */
 
1629
      keynr=0;
 
1630
      primary_key=INT_MAX;
 
1631
      while ((row= drizzleclient_fetch_row(result)))
 
1632
      {
 
1633
        if (atoi(row[3]) == 1)
 
1634
        {
 
1635
          keynr++;
 
1636
#ifdef FORCE_PRIMARY_KEY
 
1637
          if (atoi(row[1]) == 0 && primary_key == INT_MAX)
 
1638
            primary_key=keynr;
 
1639
#endif
 
1640
          if (!strcmp(row[2],"PRIMARY"))
 
1641
          {
 
1642
            primary_key=keynr;
 
1643
            break;
 
1644
          }
 
1645
        }
 
1646
      }
 
1647
      drizzleclient_data_seek(result,0);
 
1648
      keynr=0;
 
1649
      while ((row= drizzleclient_fetch_row(result)))
 
1650
      {
 
1651
        if (opt_xml)
 
1652
        {
 
1653
          print_xml_row(sql_file, "key", result, &row);
 
1654
          continue;
 
1655
        }
 
1656
 
 
1657
        if (atoi(row[3]) == 1)
 
1658
        {
 
1659
          if (keynr++)
 
1660
            putc(')', sql_file);
 
1661
          if (atoi(row[1]))       /* Test if duplicate key */
 
1662
            /* Duplicate allowed */
 
1663
            fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff,0));
 
1664
          else if (keynr == primary_key)
 
1665
            fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
 
1666
          else
 
1667
            fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff,
 
1668
                                                            0));
 
1669
        }
 
1670
        else
 
1671
          putc(',', sql_file);
 
1672
        fputs(quote_name(row[4], name_buff, 0), sql_file);
 
1673
        if (row[7])
 
1674
          fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
 
1675
        check_io(sql_file);
 
1676
      }
 
1677
      drizzleclient_free_result(result);
 
1678
      if (!opt_xml)
 
1679
      {
 
1680
        if (keynr)
 
1681
          putc(')', sql_file);
 
1682
        fputs("\n)",sql_file);
 
1683
        check_io(sql_file);
 
1684
      }
 
1685
      /* Get DRIZZLE specific create options */
 
1686
      if (create_options)
 
1687
      {
 
1688
        char show_name_buff[NAME_LEN*2+2+24];
 
1689
 
 
1690
        /* Check memory for quote_for_like() */
 
1691
        snprintf(buff, sizeof(buff), "show table status like %s",
 
1692
                 quote_for_like(table, show_name_buff));
 
1693
 
 
1694
        if (drizzleclient_query_with_error_report(drizzle, &result, buff))
 
1695
        {
 
1696
          if (drizzleclient_errno(drizzle) != ER_PARSE_ERROR)
 
1697
          {                                     /* If old DRIZZLE version */
 
1698
            verbose_msg(_("-- Warning: Couldn't get status information for " \
 
1699
                        "table %s (%s)\n"), result_table,drizzleclient_error(drizzle));
 
1700
          }
 
1701
        }
 
1702
        else if (!(row= drizzleclient_fetch_row(result)))
 
1703
        {
 
1704
          fprintf(stderr,
 
1705
                  _("Error: Couldn't read status information for table %s (%s)\n"),
 
1706
                  result_table,drizzleclient_error(drizzle));
 
1707
        }
 
1708
        else
 
1709
        {
 
1710
          if (opt_xml)
 
1711
            print_xml_row(sql_file, "options", result, &row);
 
1712
          else
 
1713
          {
 
1714
            fputs("/*!",sql_file);
 
1715
            print_value(sql_file,result,row,"engine=","Engine",0);
 
1716
            print_value(sql_file,result,row,"","Create_options",0);
 
1717
            print_value(sql_file,result,row,"comment=","Comment",1);
 
1718
 
 
1719
            fputs(" */",sql_file);
 
1720
            check_io(sql_file);
 
1721
          }
 
1722
        }
 
1723
        drizzleclient_free_result(result);              /* Is always safe to free */
 
1724
      }
 
1725
continue_xml:
 
1726
      if (!opt_xml)
 
1727
        fputs(";\n", sql_file);
 
1728
      else
 
1729
        fputs("\t</table_structure>\n", sql_file);
 
1730
      check_io(sql_file);
 
1731
    }
 
1732
  }
 
1733
  if (complete_insert) {
 
1734
    insert_pat.append(") VALUES ");
 
1735
    if (!extended_insert)
 
1736
      insert_pat.append("(");
 
1737
  }
 
1738
  if (sql_file != md_result_file)
 
1739
  {
 
1740
    fputs("\n", sql_file);
 
1741
    write_footer(sql_file);
 
1742
    my_fclose(sql_file, MYF(MY_WME));
 
1743
  }
 
1744
  return true;
 
1745
} /* get_table_structure */
 
1746
 
 
1747
static void add_load_option(string &str, const char *option,
 
1748
                            const char *option_value)
 
1749
{
 
1750
  if (!option_value)
 
1751
  {
 
1752
    /* Null value means we don't add this option. */
 
1753
    return;
 
1754
  }
 
1755
 
 
1756
  str.append(option);
 
1757
 
 
1758
  if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
 
1759
  {
 
1760
    /* It's a hex constant, don't escape */
 
1761
    str.append(option_value);
 
1762
  }
 
1763
  else
 
1764
  {
 
1765
    /* char constant; escape */
 
1766
    field_escape(str, option_value);
 
1767
  }
 
1768
}
 
1769
 
 
1770
 
 
1771
/*
 
1772
  Allow the user to specify field terminator strings like:
 
1773
  "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
 
1774
  This is done by doubling ' and add a end -\ if needed to avoid
 
1775
  syntax errors from the SQL parser.
 
1776
*/
 
1777
 
 
1778
static void field_escape(string &in, const char *from)
 
1779
{
 
1780
  uint32_t end_backslashes= 0;
 
1781
 
 
1782
  in.append("'");
 
1783
 
 
1784
  while (*from)
 
1785
  {
 
1786
    in.append(from, 1);
 
1787
 
 
1788
    if (*from == '\\')
 
1789
      end_backslashes^=1;    /* find odd number of backslashes */
 
1790
    else
 
1791
    {
 
1792
      if (*from == '\'' && !end_backslashes)
 
1793
      {
 
1794
        /* We want a duplicate of "'" for DRIZZLE */
 
1795
        in.append("\'");
 
1796
      }
 
1797
      end_backslashes=0;
 
1798
    }
 
1799
    from++;
 
1800
  }
 
1801
  /* Add missing backslashes if user has specified odd number of backs.*/
 
1802
  if (end_backslashes)
 
1803
    in.append("\\");
 
1804
 
 
1805
  in.append("'");
 
1806
}
 
1807
 
 
1808
 
 
1809
 
 
1810
/*
 
1811
 
 
1812
 SYNOPSIS
 
1813
  dump_table()
 
1814
 
 
1815
  dump_table saves database contents as a series of INSERT statements.
 
1816
 
 
1817
  ARGS
 
1818
   table - table name
 
1819
   db    - db name
 
1820
 
 
1821
   RETURNS
 
1822
    void
 
1823
*/
 
1824
 
 
1825
 
 
1826
static void dump_table(char *table, char *db)
 
1827
{
 
1828
  char ignore_flag;
 
1829
  char buf[200], table_buff[NAME_LEN+3];
 
1830
  string query_string;
 
1831
  char table_type[NAME_LEN];
 
1832
  char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
 
1833
  int error= 0;
 
1834
  uint32_t rownr, row_break, total_length, init_length;
 
1835
  uint64_t num_fields= 0;
 
1836
  DRIZZLE_RES     *res;
 
1837
  DRIZZLE_FIELD   *field;
 
1838
  DRIZZLE_ROW     row;
 
1839
 
 
1840
 
 
1841
  /*
 
1842
    Make sure you get the create table info before the following check for
 
1843
    --no-data flag below. Otherwise, the create table info won't be printed.
 
1844
  */
 
1845
  if (!get_table_structure(table, db, table_type, &ignore_flag, &num_fields))
 
1846
  {
 
1847
    maybe_die(EX_TABLE_STATUS, _("Error retrieving table structure for table: \"%s\""), table);
 
1848
    return;
 
1849
  }
 
1850
 
 
1851
  /* Check --no-data flag */
 
1852
  if (opt_no_data)
 
1853
  {
 
1854
    verbose_msg(_("-- Skipping dump data for table '%s', --no-data was used\n"),
 
1855
                table);
 
1856
    return;
 
1857
  }
 
1858
 
 
1859
  /*
 
1860
    If the table type is a merge table or any type that has to be
 
1861
     _completely_ ignored and no data dumped
 
1862
  */
 
1863
  if (ignore_flag & IGNORE_DATA)
 
1864
  {
 
1865
    verbose_msg(_("-- Warning: Skipping data for table '%s' because " \
 
1866
                "it's of type %s\n"), table, table_type);
 
1867
    return;
 
1868
  }
 
1869
  /* Check that there are any fields in the table */
 
1870
  if (num_fields == 0)
 
1871
  {
 
1872
    verbose_msg(_("-- Skipping dump data for table '%s', it has no fields\n"),
 
1873
                table);
 
1874
    return;
 
1875
  }
 
1876
 
 
1877
  result_table= quote_name(table,table_buff, 1);
 
1878
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
1879
 
 
1880
  verbose_msg(_("-- Sending SELECT query...\n"));
 
1881
 
 
1882
  query_string.clear();
 
1883
  query_string.reserve(1024);
 
1884
 
 
1885
  if (path)
 
1886
  {
 
1887
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
1888
 
 
1889
    /*
 
1890
      Convert the path to native os format
 
1891
      and resolve to the full filepath.
 
1892
    */
 
1893
    convert_dirname(tmp_path,path,NULL);
 
1894
    my_load_path(tmp_path, tmp_path, NULL);
 
1895
    fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
 
1896
 
 
1897
    /* Must delete the file that 'INTO OUTFILE' will write to */
 
1898
    my_delete(filename, MYF(0));
 
1899
 
 
1900
    /* now build the query string */
 
1901
 
 
1902
    query_string.append( "SELECT * INTO OUTFILE '");
 
1903
    query_string.append( filename);
 
1904
    query_string.append( "'");
 
1905
 
 
1906
    if (fields_terminated || enclosed || opt_enclosed || escaped)
 
1907
      query_string.append( " FIELDS");
 
1908
 
 
1909
    add_load_option(query_string, " TERMINATED BY ", fields_terminated);
 
1910
    add_load_option(query_string, " ENCLOSED BY ", enclosed);
 
1911
    add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
 
1912
    add_load_option(query_string, " ESCAPED BY ", escaped);
 
1913
    add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
 
1914
 
 
1915
    query_string.append( " FROM ");
 
1916
    query_string.append( result_table);
 
1917
 
 
1918
    if (where)
 
1919
    {
 
1920
      query_string.append( " WHERE ");
 
1921
      query_string.append( where);
 
1922
    }
 
1923
 
 
1924
    if (order_by)
 
1925
    {
 
1926
      query_string.append( " ORDER BY ");
 
1927
      query_string.append( order_by);
 
1928
    }
 
1929
 
 
1930
    if (drizzleclient_real_query(drizzle, query_string.c_str(), query_string.length()))
 
1931
    {
 
1932
      DB_error(drizzle, _("when executing 'SELECT INTO OUTFILE'"));
 
1933
      return;
 
1934
    }
 
1935
  }
 
1936
  else
 
1937
  {
 
1938
    if (!opt_xml && opt_comments)
 
1939
    {
 
1940
      fprintf(md_result_file,_("\n--\n-- Dumping data for table %s\n--\n"),
 
1941
              result_table);
 
1942
      check_io(md_result_file);
 
1943
    }
 
1944
 
 
1945
    query_string.append( "SELECT * FROM ");
 
1946
    query_string.append( result_table);
 
1947
 
 
1948
    if (where)
 
1949
    {
 
1950
      if (!opt_xml && opt_comments)
 
1951
      {
 
1952
        fprintf(md_result_file, "-- WHERE:  %s\n", where);
 
1953
        check_io(md_result_file);
 
1954
      }
 
1955
 
 
1956
      query_string.append( " WHERE ");
 
1957
      query_string.append( where);
 
1958
    }
 
1959
    if (order_by)
 
1960
    {
 
1961
      if (!opt_xml && opt_comments)
 
1962
      {
 
1963
        fprintf(md_result_file, "-- ORDER BY:  %s\n", order_by);
 
1964
        check_io(md_result_file);
 
1965
      }
 
1966
      query_string.append( " ORDER BY ");
 
1967
      query_string.append( order_by);
 
1968
    }
 
1969
 
 
1970
    if (!opt_xml && !opt_compact)
 
1971
    {
 
1972
      fputs("\n", md_result_file);
 
1973
      check_io(md_result_file);
 
1974
    }
 
1975
    if (drizzleclient_query_with_error_report(drizzle, 0, query_string.c_str()))
 
1976
    {
 
1977
      DB_error(drizzle, _("when retrieving data from server"));
 
1978
      goto err;
 
1979
    }
 
1980
    if (quick)
 
1981
      res=drizzleclient_use_result(drizzle);
 
1982
    else
 
1983
      res=drizzleclient_store_result(drizzle);
 
1984
    if (!res)
 
1985
    {
 
1986
      DB_error(drizzle, _("when retrieving data from server"));
 
1987
      goto err;
 
1988
    }
 
1989
 
 
1990
    verbose_msg(_("-- Retrieving rows...\n"));
 
1991
    if (drizzleclient_num_fields(res) != num_fields)
 
1992
    {
 
1993
      fprintf(stderr,_("%s: Error in field count for table: %s !  Aborting.\n"),
 
1994
              my_progname, result_table);
 
1995
      error= EX_CONSCHECK;
 
1996
      goto err;
 
1997
    }
 
1998
 
 
1999
    if (opt_lock)
 
2000
    {
 
2001
      fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
 
2002
      check_io(md_result_file);
 
2003
    }
 
2004
    /* Moved disable keys to after lock per bug 15977 */
 
2005
    if (opt_disable_keys)
 
2006
    {
 
2007
      fprintf(md_result_file, "ALTER TABLE %s DISABLE KEYS;\n",
 
2008
              opt_quoted_table);
 
2009
      check_io(md_result_file);
 
2010
    }
 
2011
 
 
2012
    total_length= opt_net_buffer_length;                /* Force row break */
 
2013
    row_break=0;
 
2014
    rownr=0;
 
2015
    init_length=(uint32_t) insert_pat.length()+4;
 
2016
    if (opt_xml)
 
2017
      print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
 
2018
              NULL);
 
2019
    if (opt_autocommit)
 
2020
    {
 
2021
      fprintf(md_result_file, "set autocommit=0;\n");
 
2022
      check_io(md_result_file);
 
2023
    }
 
2024
 
 
2025
    while ((row= drizzleclient_fetch_row(res)))
 
2026
    {
 
2027
      uint32_t i;
 
2028
      uint32_t *lengths= drizzleclient_fetch_lengths(res);
 
2029
      rownr++;
 
2030
      if ((rownr % show_progress_size) == 0)
 
2031
      {
 
2032
        verbose_msg(_("-- %"PRIu32" of ~%"PRIu64" rows dumped for table %s\n"), rownr, total_rows, opt_quoted_table);
 
2033
      }
 
2034
      if (!extended_insert && !opt_xml)
 
2035
      {
 
2036
        fputs(insert_pat.c_str(),md_result_file);
 
2037
        check_io(md_result_file);
 
2038
      }
 
2039
      drizzleclient_field_seek(res,0);
 
2040
 
 
2041
      if (opt_xml)
 
2042
      {
 
2043
        fputs("\t<row>\n", md_result_file);
 
2044
        check_io(md_result_file);
 
2045
      }
 
2046
 
 
2047
      for (i= 0; i < drizzleclient_num_fields(res); i++)
 
2048
      {
 
2049
        int is_blob;
 
2050
        uint32_t length= lengths[i];
 
2051
 
 
2052
        if (!(field= drizzleclient_fetch_field(res)))
 
2053
          die(EX_CONSCHECK,
 
2054
                      _("Not enough fields from table %s! Aborting.\n"),
 
2055
                      result_table);
 
2056
 
 
2057
        /*
 
2058
           63 is my_charset_bin. If charsetnr is not 63,
 
2059
           we have not a BLOB but a TEXT column.
 
2060
           we'll dump in hex only BLOB columns.
 
2061
        */
 
2062
        is_blob= (opt_hex_blob && field->charsetnr == 63 &&
 
2063
                  (field->type == DRIZZLE_TYPE_VARCHAR ||
 
2064
                   field->type == DRIZZLE_TYPE_BLOB)) ? 1 : 0;
 
2065
        if (extended_insert && !opt_xml)
 
2066
        {
 
2067
          if (i == 0)
 
2068
          {
 
2069
            extended_row.clear();
 
2070
            extended_row.append("(");
 
2071
          }
 
2072
          else
 
2073
            extended_row.append(",");
 
2074
 
 
2075
          if (row[i])
 
2076
          {
 
2077
            if (length)
 
2078
            {
 
2079
              if (!(field->type & NUM_FLAG))
 
2080
              {
 
2081
                /*
 
2082
                  "length * 2 + 2" is OK for both HEX and non-HEX modes:
 
2083
                  - In HEX mode we need exactly 2 bytes per character
 
2084
                  plus 2 bytes for '0x' prefix.
 
2085
                  - In non-HEX mode we need up to 2 bytes per character,
 
2086
                  plus 2 bytes for leading and trailing '\'' characters.
 
2087
                  Also we need to reserve 1 byte for terminating '\0'.
 
2088
                */
 
2089
                char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
 
2090
                memset(tmp_str, '\0', length * 2 + 2 + 1);
 
2091
                if (opt_hex_blob && is_blob)
 
2092
                {
 
2093
                  extended_row.append("0x");
 
2094
                  drizzleclient_drizzleclient_octet2hex(tmp_str, row[i], length);
 
2095
                  extended_row.append(tmp_str);
 
2096
                }
 
2097
                else
 
2098
                {
 
2099
                  extended_row.append("'");
 
2100
                  drizzleclient_escape_string(tmp_str,
 
2101
                                        row[i],length);
 
2102
                  extended_row.append(tmp_str);
 
2103
                  extended_row.append("'");
 
2104
                }
 
2105
                free(tmp_str);
 
2106
              }
 
2107
              else
 
2108
              {
 
2109
                /* change any strings ("inf", "-inf", "nan") into NULL */
 
2110
                char *ptr= row[i];
 
2111
                if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
 
2112
                    my_isalpha(charset_info, ptr[1])))
 
2113
                  extended_row.append( "NULL");
 
2114
                else
 
2115
                {
 
2116
                  extended_row.append( ptr);
 
2117
                }
 
2118
              }
 
2119
            }
 
2120
            else
 
2121
              extended_row.append("''");
 
2122
          }
 
2123
          else
 
2124
            extended_row.append("NULL");
 
2125
        }
 
2126
        else
 
2127
        {
 
2128
          if (i && !opt_xml)
 
2129
          {
 
2130
            fputc(',', md_result_file);
 
2131
            check_io(md_result_file);
 
2132
          }
 
2133
          if (row[i])
 
2134
          {
 
2135
            if (!(field->type & NUM_FLAG))
 
2136
            {
 
2137
              if (opt_xml)
 
2138
              {
 
2139
                if (opt_hex_blob && is_blob && length)
 
2140
                {
 
2141
                  /* Define xsi:type="xs:hexBinary" for hex encoded data */
 
2142
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2143
                                field->name, "xsi:type=", "xs:hexBinary", NULL);
 
2144
                  print_blob_as_hex(md_result_file, row[i], length);
 
2145
                }
 
2146
                else
 
2147
                {
 
2148
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2149
                                field->name, NULL);
 
2150
                  print_quoted_xml(md_result_file, row[i], length);
 
2151
                }
 
2152
                fputs("</field>\n", md_result_file);
 
2153
              }
 
2154
              else if (opt_hex_blob && is_blob && length)
 
2155
              {
 
2156
                fputs("0x", md_result_file);
 
2157
                print_blob_as_hex(md_result_file, row[i], length);
 
2158
              }
 
2159
              else
 
2160
                unescape(md_result_file, row[i], length);
 
2161
            }
 
2162
            else
 
2163
            {
 
2164
              /* change any strings ("inf", "-inf", "nan") into NULL */
 
2165
              char *ptr= row[i];
 
2166
              if (opt_xml)
 
2167
              {
 
2168
                print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2169
                        field->name, NULL);
 
2170
                fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
 
2171
                      md_result_file);
 
2172
                fputs("</field>\n", md_result_file);
 
2173
              }
 
2174
              else if (my_isalpha(charset_info, *ptr) ||
 
2175
                       (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
 
2176
                fputs("NULL", md_result_file);
 
2177
              else
 
2178
                fputs(ptr, md_result_file);
 
2179
            }
 
2180
          }
 
2181
          else
 
2182
          {
 
2183
            /* The field value is NULL */
 
2184
            if (!opt_xml)
 
2185
              fputs("NULL", md_result_file);
 
2186
            else
 
2187
              print_xml_null_tag(md_result_file, "\t\t", "field name=",
 
2188
                                 field->name, "\n");
 
2189
          }
 
2190
          check_io(md_result_file);
 
2191
        }
 
2192
      }
 
2193
 
 
2194
      if (opt_xml)
 
2195
      {
 
2196
        fputs("\t</row>\n", md_result_file);
 
2197
        check_io(md_result_file);
 
2198
      }
 
2199
 
 
2200
      if (extended_insert)
 
2201
      {
 
2202
        uint32_t row_length;
 
2203
        extended_row.append(")");
 
2204
        row_length= 2 + extended_row.length();
 
2205
        if (total_length + row_length < opt_net_buffer_length)
 
2206
        {
 
2207
          total_length+= row_length;
 
2208
          fputc(',',md_result_file);            /* Always row break */
 
2209
          fputs(extended_row.c_str(),md_result_file);
 
2210
        }
 
2211
        else
 
2212
        {
 
2213
          if (row_break)
 
2214
            fputs(";\n", md_result_file);
 
2215
          row_break=1;                          /* This is first row */
 
2216
 
 
2217
          fputs(insert_pat.c_str(),md_result_file);
 
2218
          fputs(extended_row.c_str(),md_result_file);
 
2219
          total_length= row_length+init_length;
 
2220
        }
 
2221
        check_io(md_result_file);
 
2222
      }
 
2223
      else if (!opt_xml)
 
2224
      {
 
2225
        fputs(");\n", md_result_file);
 
2226
        check_io(md_result_file);
 
2227
      }
 
2228
    }
 
2229
 
 
2230
    /* XML - close table tag and supress regular output */
 
2231
    if (opt_xml)
 
2232
        fputs("\t</table_data>\n", md_result_file);
 
2233
    else if (extended_insert && row_break)
 
2234
      fputs(";\n", md_result_file);             /* If not empty table */
 
2235
    fflush(md_result_file);
 
2236
    check_io(md_result_file);
 
2237
    if (drizzleclient_errno(drizzle))
 
2238
    {
 
2239
      snprintf(buf, sizeof(buf),
 
2240
               _("%s: Error %d: %s when dumping table %s at row: %d\n"),
 
2241
               my_progname,
 
2242
               drizzleclient_errno(drizzle),
 
2243
               drizzleclient_error(drizzle),
 
2244
               result_table,
 
2245
               rownr);
 
2246
      fputs(buf,stderr);
 
2247
      error= EX_CONSCHECK;
 
2248
      goto err;
 
2249
    }
 
2250
 
 
2251
    /* Moved enable keys to before unlock per bug 15977 */
 
2252
    if (opt_disable_keys)
 
2253
    {
 
2254
      fprintf(md_result_file,"ALTER TABLE %s ENABLE KEYS;\n",
 
2255
              opt_quoted_table);
 
2256
      check_io(md_result_file);
 
2257
    }
 
2258
    if (opt_lock)
 
2259
    {
 
2260
      fputs("UNLOCK TABLES;\n", md_result_file);
 
2261
      check_io(md_result_file);
 
2262
    }
 
2263
    if (opt_autocommit)
 
2264
    {
 
2265
      fprintf(md_result_file, "commit;\n");
 
2266
      check_io(md_result_file);
 
2267
    }
 
2268
    drizzleclient_free_result(res);
 
2269
  }
 
2270
  return;
 
2271
 
 
2272
err:
 
2273
  maybe_exit(error);
 
2274
  return;
 
2275
} /* dump_table */
 
2276
 
 
2277
 
 
2278
static char *getTableName(int reset)
 
2279
{
 
2280
  static DRIZZLE_RES *res= NULL;
 
2281
  DRIZZLE_ROW    row;
 
2282
 
 
2283
  if (!res)
 
2284
  {
 
2285
    if (!(res= drizzleclient_list_tables(drizzle,NULL)))
 
2286
      return(NULL);
 
2287
  }
 
2288
  if ((row= drizzleclient_fetch_row(res)))
 
2289
    return((char*) row[0]);
 
2290
 
 
2291
  if (reset)
 
2292
    drizzleclient_data_seek(res,0);      /* We want to read again */
 
2293
  else
 
2294
  {
 
2295
    drizzleclient_free_result(res);
 
2296
    res= NULL;
 
2297
  }
 
2298
  return(NULL);
 
2299
} /* getTableName */
 
2300
 
 
2301
 
365
2302
static int dump_all_databases()
366
2303
{
367
 
  drizzle_row_t row;
368
 
  drizzle_result_st *tableres;
 
2304
  DRIZZLE_ROW row;
 
2305
  DRIZZLE_RES *tableres;
369
2306
  int result=0;
370
 
  std::string query;
371
 
  DrizzleDumpDatabase *database;
372
 
 
373
 
  if (verbose)
374
 
    std::cerr << _("-- Retrieving database structures...") << std::endl;
375
 
 
376
 
  /* Blocking the MySQL privilege tables too because we can't import them due to bug#646187 */
377
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
378
 
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')";
379
 
  else
380
 
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM DATA_DICTIONARY.SCHEMAS WHERE SCHEMA_NAME NOT IN ('information_schema','data_dictionary')";
381
 
 
382
 
  tableres= db_connection->query(query);
383
 
  while ((row= drizzle_row_next(tableres)))
 
2307
 
 
2308
  if (drizzleclient_query_with_error_report(drizzle, &tableres, "SHOW DATABASES"))
 
2309
    return 1;
 
2310
  while ((row= drizzleclient_fetch_row(tableres)))
384
2311
  {
385
 
    std::string database_name(row[0]);
386
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
387
 
      database= new DrizzleDumpDatabaseMySQL(database_name, db_connection);
388
 
    else
389
 
      database= new DrizzleDumpDatabaseDrizzle(database_name, db_connection);
390
 
 
391
 
    database->setCollate(row[1]);
392
 
    database_store.push_back(database);
 
2312
    if (dump_all_tables_in_db(row[0]))
 
2313
      result=1;
393
2314
  }
394
 
  db_connection->freeResult(tableres);
395
2315
  return result;
396
2316
}
397
2317
/* dump_all_databases */
398
2318
 
399
2319
 
400
 
static int dump_databases(const vector<string> &db_names)
 
2320
static int dump_databases(char **db_names)
401
2321
{
402
2322
  int result=0;
403
 
  string temp;
404
 
  DrizzleDumpDatabase *database;
405
 
 
406
 
  for (vector<string>::const_iterator it= db_names.begin(); it != db_names.end(); ++it)
 
2323
  char **db;
 
2324
 
 
2325
 
 
2326
  for (db= db_names ; *db ; db++)
407
2327
  {
408
 
    temp= *it;
409
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
410
 
      database= new DrizzleDumpDatabaseMySQL(temp, db_connection);
411
 
    else
412
 
      database= new DrizzleDumpDatabaseDrizzle(temp, db_connection);
413
 
    database_store.push_back(database);
 
2328
    if (dump_all_tables_in_db(*db))
 
2329
      result=1;
414
2330
  }
415
2331
  return(result);
416
2332
} /* dump_databases */
417
2333
 
418
 
static int dump_selected_tables(const string &db, const vector<string> &table_names)
419
 
{
420
 
  DrizzleDumpDatabase *database;
421
 
 
422
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
423
 
    database= new DrizzleDumpDatabaseMySQL(db, db_connection);
424
 
  else
425
 
    database= new DrizzleDumpDatabaseDrizzle(db, db_connection);
426
 
 
427
 
  if (not database->populateTables(table_names))
428
 
  {
429
 
    delete database;
430
 
    if (not ignore_errors)
431
 
      maybe_exit(EX_DRIZZLEERR);
432
 
  }
433
 
 
434
 
  database_store.push_back(database); 
435
 
 
 
2334
 
 
2335
/*
 
2336
Table Specific database initalization.
 
2337
 
 
2338
SYNOPSIS
 
2339
  init_dumping_tables
 
2340
  qdatabase      quoted name of the database
 
2341
 
 
2342
RETURN VALUES
 
2343
  0        Success.
 
2344
  1        Failure.
 
2345
*/
 
2346
 
 
2347
int init_dumping_tables(char *qdatabase)
 
2348
{
 
2349
 
 
2350
 
 
2351
  if (!opt_create_db)
 
2352
  {
 
2353
    char qbuf[256];
 
2354
    DRIZZLE_ROW row;
 
2355
    DRIZZLE_RES *dbinfo;
 
2356
 
 
2357
    snprintf(qbuf, sizeof(qbuf),
 
2358
             "SHOW CREATE DATABASE IF NOT EXISTS %s",
 
2359
             qdatabase);
 
2360
 
 
2361
    if (drizzleclient_query(drizzle, qbuf) || !(dbinfo = drizzleclient_store_result(drizzle)))
 
2362
    {
 
2363
      /* Old server version, dump generic CREATE DATABASE */
 
2364
      if (opt_drop_database)
 
2365
        fprintf(md_result_file,
 
2366
                "\nDROP DATABASE IF EXISTS %s;\n",
 
2367
                qdatabase);
 
2368
      fprintf(md_result_file,
 
2369
              "\nCREATE DATABASE IF NOT EXISTS %s;\n",
 
2370
              qdatabase);
 
2371
    }
 
2372
    else
 
2373
    {
 
2374
      if (opt_drop_database)
 
2375
        fprintf(md_result_file,
 
2376
                "\nDROP DATABASE IF EXISTS %s;\n",
 
2377
                qdatabase);
 
2378
      row = drizzleclient_fetch_row(dbinfo);
 
2379
      if (row[1])
 
2380
      {
 
2381
        fprintf(md_result_file,"\n%s;\n",row[1]);
 
2382
      }
 
2383
      drizzleclient_free_result(dbinfo);
 
2384
    }
 
2385
  }
 
2386
  return(0);
 
2387
} /* init_dumping_tables */
 
2388
 
 
2389
 
 
2390
static int init_dumping(char *database, int init_func(char*))
 
2391
{
 
2392
  if (drizzleclient_get_server_version(drizzle) >= 50003 &&
 
2393
      !my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
 
2394
    return 1;
 
2395
 
 
2396
  if (drizzleclient_select_db(drizzle, database))
 
2397
  {
 
2398
    DB_error(drizzle, _("when selecting the database"));
 
2399
    return 1;                   /* If --force */
 
2400
  }
 
2401
  if (!path && !opt_xml)
 
2402
  {
 
2403
    if (opt_databases || opt_alldbs)
 
2404
    {
 
2405
      /*
 
2406
        length of table name * 2 (if name contains quotes), 2 quotes and 0
 
2407
      */
 
2408
      char quoted_database_buf[NAME_LEN*2+3];
 
2409
      char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
 
2410
      if (opt_comments)
 
2411
      {
 
2412
        fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
 
2413
        check_io(md_result_file);
 
2414
      }
 
2415
 
 
2416
      /* Call the view or table specific function */
 
2417
      init_func(qdatabase);
 
2418
 
 
2419
      fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
 
2420
      check_io(md_result_file);
 
2421
    }
 
2422
  }
 
2423
  if (extended_insert)
 
2424
    extended_row.clear();
436
2425
  return 0;
 
2426
} /* init_dumping */
 
2427
 
 
2428
 
 
2429
/* Return 1 if we should copy the table */
 
2430
 
 
2431
static bool include_table(const unsigned char *hash_key, size_t len)
 
2432
{
 
2433
  return !hash_search(&ignore_table, hash_key, len);
 
2434
}
 
2435
 
 
2436
 
 
2437
static int dump_all_tables_in_db(char *database)
 
2438
{
 
2439
  char *table;
 
2440
  uint32_t numrows;
 
2441
  char table_buff[NAME_LEN*2+3];
 
2442
  char hash_key[2*NAME_LEN+2];  /* "db.tablename" */
 
2443
  char *afterdot;
 
2444
 
 
2445
  afterdot= strcpy(hash_key, database) + strlen(database);
 
2446
  *afterdot++= '.';
 
2447
 
 
2448
  if (init_dumping(database, init_dumping_tables))
 
2449
    return(1);
 
2450
  if (opt_xml)
 
2451
    print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NULL);
 
2452
  if (lock_tables)
 
2453
  {
 
2454
    string query("LOCK TABLES ");
 
2455
    for (numrows= 0 ; (table= getTableName(1)) ; )
 
2456
    {
 
2457
      char *end= strcpy(afterdot, table) + strlen(table);
 
2458
      if (include_table((unsigned char*) hash_key,end - hash_key))
 
2459
      {
 
2460
        numrows++;
 
2461
        query.append( quote_name(table, table_buff, 1));
 
2462
        query.append( " READ LOCAL,");
 
2463
      }
 
2464
    }
 
2465
    if (numrows && drizzleclient_real_query(drizzle, query.c_str(), query.length()-1))
 
2466
      DB_error(drizzle, _("when using LOCK TABLES"));
 
2467
            /* We shall continue here, if --force was given */
 
2468
    query.clear();
 
2469
  }
 
2470
  if (flush_logs)
 
2471
  {
 
2472
    if (drizzleclient_refresh(drizzle, REFRESH_LOG))
 
2473
      DB_error(drizzle, _("when doing refresh"));
 
2474
           /* We shall continue here, if --force was given */
 
2475
  }
 
2476
  while ((table= getTableName(0)))
 
2477
  {
 
2478
    char *end= strcpy(afterdot, table) + strlen(table);
 
2479
    if (include_table((unsigned char*) hash_key, end - hash_key))
 
2480
    {
 
2481
      dump_table(table,database);
 
2482
      free(order_by);
 
2483
      order_by= 0;
 
2484
    }
 
2485
  }
 
2486
  if (opt_xml)
 
2487
  {
 
2488
    fputs("</database>\n", md_result_file);
 
2489
    check_io(md_result_file);
 
2490
  }
 
2491
  if (lock_tables)
 
2492
    drizzleclient_query_with_error_report(drizzle, 0, "UNLOCK TABLES");
 
2493
 
 
2494
  return(0);
 
2495
} /* dump_all_tables_in_db */
 
2496
 
 
2497
 
 
2498
/*
 
2499
  get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
 
2500
  table name from the server for the table name given on the command line.
 
2501
  we do this because the table name given on the command line may be a
 
2502
  different case (e.g.  T1 vs t1)
 
2503
 
 
2504
  RETURN
 
2505
    pointer to the table name
 
2506
    0 if error
 
2507
*/
 
2508
 
 
2509
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
 
2510
{
 
2511
  char *name= 0;
 
2512
  DRIZZLE_RES  *table_res;
 
2513
  DRIZZLE_ROW  row;
 
2514
  char query[50 + 2*NAME_LEN];
 
2515
  char show_name_buff[FN_REFLEN];
 
2516
 
 
2517
 
 
2518
  /* Check memory for quote_for_like() */
 
2519
  assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
 
2520
  snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
 
2521
           quote_for_like(old_table_name, show_name_buff));
 
2522
 
 
2523
  if (drizzleclient_query_with_error_report(drizzle, 0, query))
 
2524
    return NULL;
 
2525
 
 
2526
  if ((table_res= drizzleclient_store_result(drizzle)))
 
2527
  {
 
2528
    uint64_t num_rows= drizzleclient_num_rows(table_res);
 
2529
    if (num_rows > 0)
 
2530
    {
 
2531
      uint32_t *lengths;
 
2532
      /*
 
2533
        Return first row
 
2534
        TODO: Return all matching rows
 
2535
      */
 
2536
      row= drizzleclient_fetch_row(table_res);
 
2537
      lengths= drizzleclient_fetch_lengths(table_res);
 
2538
      name= strmake_root(root, row[0], lengths[0]);
 
2539
    }
 
2540
    drizzleclient_free_result(table_res);
 
2541
  }
 
2542
  return(name);
 
2543
}
 
2544
 
 
2545
 
 
2546
static int dump_selected_tables(char *db, char **table_names, int tables)
 
2547
{
 
2548
  char table_buff[NAME_LEN*2+3];
 
2549
  string lock_tables_query("LOCK TABLES ");
 
2550
  MEM_ROOT root;
 
2551
  char **dump_tables, **pos, **end;
 
2552
 
 
2553
 
 
2554
  if (init_dumping(db, init_dumping_tables))
 
2555
    return(1);
 
2556
 
 
2557
  init_alloc_root(&root, 8192, 0);
 
2558
  if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
 
2559
     die(EX_EOM, _("alloc_root failure."));
 
2560
 
 
2561
  for (; tables > 0 ; tables-- , table_names++)
 
2562
  {
 
2563
    /* the table name passed on commandline may be wrong case */
 
2564
    if ((*pos= get_actual_table_name(*table_names, &root)))
 
2565
    {
 
2566
      /* Add found table name to lock_tables_query */
 
2567
      if (lock_tables)
 
2568
      {
 
2569
        lock_tables_query.append( quote_name(*pos, table_buff, 1));
 
2570
        lock_tables_query.append( " READ LOCAL,");
 
2571
      }
 
2572
      pos++;
 
2573
    }
 
2574
    else
 
2575
    {
 
2576
      if (!ignore_errors)
 
2577
      {
 
2578
        free_root(&root, MYF(0));
 
2579
      }
 
2580
      maybe_die(EX_ILLEGAL_TABLE, _("Couldn't find table: \"%s\""), *table_names);
 
2581
      /* We shall countinue here, if --force was given */
 
2582
    }
 
2583
  }
 
2584
  end= pos;
 
2585
 
 
2586
  if (lock_tables)
 
2587
  {
 
2588
    if (drizzleclient_real_query(drizzle, lock_tables_query.c_str(),
 
2589
                         lock_tables_query.length()-1))
 
2590
    {
 
2591
      if (!ignore_errors)
 
2592
      {
 
2593
        free_root(&root, MYF(0));
 
2594
      }
 
2595
      DB_error(drizzle, _("when doing LOCK TABLES"));
 
2596
       /* We shall countinue here, if --force was given */
 
2597
    }
 
2598
  }
 
2599
  if (flush_logs)
 
2600
  {
 
2601
    if (drizzleclient_refresh(drizzle, REFRESH_LOG))
 
2602
    {
 
2603
      if (!ignore_errors)
 
2604
        free_root(&root, MYF(0));
 
2605
      DB_error(drizzle, _("when doing refresh"));
 
2606
    }
 
2607
     /* We shall countinue here, if --force was given */
 
2608
  }
 
2609
  if (opt_xml)
 
2610
    print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NULL);
 
2611
 
 
2612
  /* Dump each selected table */
 
2613
  for (pos= dump_tables; pos < end; pos++)
 
2614
    dump_table(*pos, db);
 
2615
 
 
2616
  free_root(&root, MYF(0));
 
2617
  free(order_by);
 
2618
  order_by= 0;
 
2619
  if (opt_xml)
 
2620
  {
 
2621
    fputs("</database>\n", md_result_file);
 
2622
    check_io(md_result_file);
 
2623
  }
 
2624
  if (lock_tables)
 
2625
    drizzleclient_query_with_error_report(drizzle, 0, "UNLOCK TABLES");
 
2626
  return(0);
437
2627
} /* dump_selected_tables */
438
2628
 
439
 
static int do_flush_tables_read_lock()
 
2629
 
 
2630
static int do_show_master_status(DRIZZLE *drizzle_con)
 
2631
{
 
2632
  DRIZZLE_ROW row;
 
2633
  DRIZZLE_RES *master;
 
2634
  const char *comment_prefix=
 
2635
    (opt_master_data == DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
 
2636
  if (drizzleclient_query_with_error_report(drizzle_con, &master, "SHOW MASTER STATUS"))
 
2637
  {
 
2638
    return 1;
 
2639
  }
 
2640
  else
 
2641
  {
 
2642
    row= drizzleclient_fetch_row(master);
 
2643
    if (row && row[0] && row[1])
 
2644
    {
 
2645
      /* SHOW MASTER STATUS reports file and position */
 
2646
      if (opt_comments)
 
2647
        fprintf(md_result_file,
 
2648
                "\n--\n-- Position to start replication or point-in-time "
 
2649
                "recovery from\n--\n\n");
 
2650
      fprintf(md_result_file,
 
2651
              "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
 
2652
              comment_prefix, row[0], row[1]);
 
2653
      check_io(md_result_file);
 
2654
    }
 
2655
    else if (!ignore_errors)
 
2656
    {
 
2657
      /* SHOW MASTER STATUS reports nothing and --force is not enabled */
 
2658
      my_printf_error(0, _("Error: Binlogging on server not active"),
 
2659
                      MYF(0));
 
2660
      drizzleclient_free_result(master);
 
2661
      maybe_exit(EX_DRIZZLEERR);
 
2662
      return 1;
 
2663
    }
 
2664
    drizzleclient_free_result(master);
 
2665
  }
 
2666
  return 0;
 
2667
}
 
2668
 
 
2669
static int do_stop_slave_sql(DRIZZLE *drizzle_con)
 
2670
{
 
2671
  DRIZZLE_RES *slave;
 
2672
  /* We need to check if the slave sql is running in the first place */
 
2673
  if (drizzleclient_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
 
2674
    return(1);
 
2675
  else
 
2676
  {
 
2677
    DRIZZLE_ROW row= drizzleclient_fetch_row(slave);
 
2678
    if (row && row[11])
 
2679
    {
 
2680
      /* if SLAVE SQL is not running, we don't stop it */
 
2681
      if (!strcmp(row[11],"No"))
 
2682
      {
 
2683
        drizzleclient_free_result(slave);
 
2684
        /* Silently assume that they don't have the slave running */
 
2685
        return(0);
 
2686
      }
 
2687
    }
 
2688
  }
 
2689
  drizzleclient_free_result(slave);
 
2690
 
 
2691
  /* now, stop slave if running */
 
2692
  if (drizzleclient_query_with_error_report(drizzle_con, 0, "STOP SLAVE SQL_THREAD"))
 
2693
    return(1);
 
2694
 
 
2695
  return(0);
 
2696
}
 
2697
 
 
2698
static int add_stop_slave(void)
 
2699
{
 
2700
  if (opt_comments)
 
2701
    fprintf(md_result_file,
 
2702
            "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
 
2703
  fprintf(md_result_file, "STOP SLAVE;\n");
 
2704
  return(0);
 
2705
}
 
2706
 
 
2707
static int add_slave_statements(void)
 
2708
{
 
2709
  if (opt_comments)
 
2710
    fprintf(md_result_file,
 
2711
            "\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
 
2712
  fprintf(md_result_file, "START SLAVE;\n");
 
2713
  return(0);
 
2714
}
 
2715
 
 
2716
static int do_show_slave_status(DRIZZLE *drizzle_con)
 
2717
{
 
2718
  DRIZZLE_RES *slave;
 
2719
  const char *comment_prefix=
 
2720
    (opt_slave_data == DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
 
2721
  if (drizzleclient_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
 
2722
  {
 
2723
    if (!ignore_errors)
 
2724
    {
 
2725
      /* SHOW SLAVE STATUS reports nothing and --force is not enabled */
 
2726
      my_printf_error(0, _("Error: Slave not set up"), MYF(0));
 
2727
    }
 
2728
    return 1;
 
2729
  }
 
2730
  else
 
2731
  {
 
2732
    DRIZZLE_ROW row= drizzleclient_fetch_row(slave);
 
2733
    if (row && row[9] && row[21])
 
2734
    {
 
2735
      /* SHOW MASTER STATUS reports file and position */
 
2736
      if (opt_comments)
 
2737
        fprintf(md_result_file,
 
2738
                "\n--\n-- Position to start replication or point-in-time "
 
2739
                "recovery from (the master of this slave)\n--\n\n");
 
2740
 
 
2741
      fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
 
2742
 
 
2743
      if (opt_include_master_host_port)
 
2744
      {
 
2745
        if (row[1])
 
2746
          fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
 
2747
        if (row[3])
 
2748
          fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
 
2749
      }
 
2750
      fprintf(md_result_file,
 
2751
              "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
 
2752
 
 
2753
      check_io(md_result_file);
 
2754
    }
 
2755
    drizzleclient_free_result(slave);
 
2756
  }
 
2757
  return 0;
 
2758
}
 
2759
 
 
2760
static int do_start_slave_sql(DRIZZLE *drizzle_con)
 
2761
{
 
2762
  DRIZZLE_RES *slave;
 
2763
  /* We need to check if the slave sql is stopped in the first place */
 
2764
  if (drizzleclient_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS"))
 
2765
    return(1);
 
2766
  else
 
2767
  {
 
2768
    DRIZZLE_ROW row= drizzleclient_fetch_row(slave);
 
2769
    if (row && row[11])
 
2770
    {
 
2771
      /* if SLAVE SQL is not running, we don't start it */
 
2772
      if (!strcmp(row[11],"Yes"))
 
2773
      {
 
2774
        drizzleclient_free_result(slave);
 
2775
        /* Silently assume that they don't have the slave running */
 
2776
        return(0);
 
2777
      }
 
2778
    }
 
2779
  }
 
2780
  drizzleclient_free_result(slave);
 
2781
 
 
2782
  /* now, start slave if stopped */
 
2783
  if (drizzleclient_query_with_error_report(drizzle_con, 0, "START SLAVE"))
 
2784
  {
 
2785
    my_printf_error(0, _("Error: Unable to start slave"), MYF(0));
 
2786
    return 1;
 
2787
  }
 
2788
  return(0);
 
2789
}
 
2790
 
 
2791
 
 
2792
 
 
2793
static int do_flush_tables_read_lock(DRIZZLE *drizzle_con)
440
2794
{
441
2795
  /*
442
2796
    We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
443
2797
    will wait but will not stall the whole mysqld, and when the long update is
444
2798
    done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
445
 
    FLUSH TABLES is to lower the probability of a stage where both drizzled
 
2799
    FLUSH TABLES is to lower the probability of a stage where both mysqldump
446
2800
    and most client connections are stalled. Of course, if a second long
447
2801
    update starts between the two FLUSHes, we have that bad stall.
448
2802
  */
449
 
 
450
 
   db_connection->queryNoResult("FLUSH TABLES");
451
 
   db_connection->queryNoResult("FLUSH TABLES WITH READ LOCK");
452
 
 
453
 
  return 0;
454
 
}
455
 
 
456
 
static int do_unlock_tables()
457
 
{
458
 
  db_connection->queryNoResult("UNLOCK TABLES");
459
 
  return 0;
460
 
}
461
 
 
462
 
static int start_transaction()
463
 
{
464
 
  db_connection->queryNoResult("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ");
465
 
  db_connection->queryNoResult("START TRANSACTION WITH CONSISTENT SNAPSHOT");
466
 
  return 0;
467
 
}
 
2803
  return
 
2804
    ( drizzleclient_query_with_error_report(drizzle_con, 0, "FLUSH TABLES") ||
 
2805
      drizzleclient_query_with_error_report(drizzle_con, 0,
 
2806
                                    "FLUSH TABLES WITH READ LOCK") );
 
2807
}
 
2808
 
 
2809
 
 
2810
static int do_unlock_tables(DRIZZLE *drizzle_con)
 
2811
{
 
2812
  return drizzleclient_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES");
 
2813
}
 
2814
 
 
2815
static int get_bin_log_name(DRIZZLE *drizzle_con,
 
2816
                            char* buff_log_name, uint32_t buff_len)
 
2817
{
 
2818
  DRIZZLE_RES *res;
 
2819
  DRIZZLE_ROW row;
 
2820
 
 
2821
  if (drizzleclient_query(drizzle_con, "SHOW MASTER STATUS") ||
 
2822
      !(res= drizzleclient_store_result(drizzle)))
 
2823
    return 1;
 
2824
 
 
2825
  if (!(row= drizzleclient_fetch_row(res)))
 
2826
  {
 
2827
    drizzleclient_free_result(res);
 
2828
    return 1;
 
2829
  }
 
2830
  /*
 
2831
    Only one row is returned, and the first column is the name of the
 
2832
    active log.
 
2833
  */
 
2834
  strncpy(buff_log_name, row[0], buff_len - 1);
 
2835
 
 
2836
  drizzleclient_free_result(res);
 
2837
  return 0;
 
2838
}
 
2839
 
 
2840
static int purge_bin_logs_to(DRIZZLE *drizzle_con, char* log_name)
 
2841
{
 
2842
  int err;
 
2843
  string str= "PURGE BINARY LOGS TO '";
 
2844
  str.append(log_name);
 
2845
  str.append("'");
 
2846
  err = drizzleclient_query_with_error_report(drizzle_con, 0, str.c_str());
 
2847
  return err;
 
2848
}
 
2849
 
 
2850
 
 
2851
static int start_transaction(DRIZZLE *drizzle_con)
 
2852
{
 
2853
  return (drizzleclient_query_with_error_report(drizzle_con, 0,
 
2854
                                        "SET SESSION TRANSACTION ISOLATION "
 
2855
                                        "LEVEL REPEATABLE READ") ||
 
2856
          drizzleclient_query_with_error_report(drizzle_con, 0,
 
2857
                                        "START TRANSACTION "
 
2858
                                        "WITH CONSISTENT SNAPSHOT"));
 
2859
}
 
2860
 
 
2861
 
 
2862
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
 
2863
                      char **err_pos, uint32_t *err_len)
 
2864
{
 
2865
  const char *end= x + length;
 
2866
  uint32_t found= 0;
 
2867
  uint32_t find;
 
2868
  char buff[255];
 
2869
 
 
2870
  *err_pos= 0;                  /* No error yet */
 
2871
  while (end > x && my_isspace(charset_info, end[-1]))
 
2872
    end--;
 
2873
 
 
2874
  *err_len= 0;
 
2875
  if (x != end)
 
2876
  {
 
2877
    const char *start= x;
 
2878
    for (;;)
 
2879
    {
 
2880
      const char *pos= start;
 
2881
      uint32_t var_len;
 
2882
 
 
2883
      for (; pos != end && *pos != ','; pos++) ;
 
2884
      var_len= (uint32_t) (pos - start);
 
2885
      strncpy(buff, start, min((uint32_t)sizeof(buff), var_len));
 
2886
      find= find_type(buff, lib, var_len);
 
2887
      if (!find)
 
2888
      {
 
2889
        *err_pos= (char*) start;
 
2890
        *err_len= var_len;
 
2891
      }
 
2892
      else
 
2893
        found|= (uint32_t)((int64_t) 1 << (find - 1));
 
2894
      if (pos == end)
 
2895
        break;
 
2896
      start= pos + 1;
 
2897
    }
 
2898
  }
 
2899
  return found;
 
2900
}
 
2901
 
 
2902
 
 
2903
/* Print a value with a prefix on file */
 
2904
static void print_value(FILE *file, DRIZZLE_RES  *result, DRIZZLE_ROW row,
 
2905
                        const char *prefix, const char *name,
 
2906
                        int string_value)
 
2907
{
 
2908
  DRIZZLE_FIELD   *field;
 
2909
  drizzleclient_field_seek(result, 0);
 
2910
 
 
2911
  for ( ; (field= drizzleclient_fetch_field(result)) ; row++)
 
2912
  {
 
2913
    if (!strcmp(field->name,name))
 
2914
    {
 
2915
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
2916
      {
 
2917
        fputc(' ',file);
 
2918
        fputs(prefix, file);
 
2919
        if (string_value)
 
2920
          unescape(file,row[0],(uint32_t) strlen(row[0]));
 
2921
        else
 
2922
          fputs(row[0], file);
 
2923
        check_io(file);
 
2924
        return;
 
2925
      }
 
2926
    }
 
2927
  }
 
2928
  return;                                       /* This shouldn't happen */
 
2929
} /* print_value */
 
2930
 
 
2931
/**
 
2932
 * Fetches a row from a result based on a field name
 
2933
 * Returns const char* of the data in that row or NULL if not found
 
2934
 */
 
2935
 
 
2936
static const char* fetch_named_row(DRIZZLE_RES *result, DRIZZLE_ROW row, const char *name)
 
2937
{
 
2938
  DRIZZLE_FIELD   *field;
 
2939
  drizzleclient_field_seek(result, 0);
 
2940
  for ( ; (field= drizzleclient_fetch_field(result)) ; row++)
 
2941
  {
 
2942
    if (!strcmp(field->name,name))
 
2943
    {
 
2944
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
2945
      {
 
2946
        drizzleclient_field_seek(result, 0);
 
2947
        return row[0];
 
2948
      }
 
2949
    }
 
2950
  }
 
2951
  drizzleclient_field_seek(result, 0);
 
2952
  return NULL;
 
2953
}
 
2954
 
 
2955
 
 
2956
/*
 
2957
  SYNOPSIS
 
2958
 
 
2959
  Check if we the table is one of the table types that should be ignored:
 
2960
  MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
 
2961
  If the table should be altogether ignored, it returns a true, false if it
 
2962
  should not be ignored. If the user has selected to use INSERT DELAYED, it
 
2963
  sets the value of the bool pointer supports_delayed_inserts to 0 if not
 
2964
  supported, 1 if it is supported.
 
2965
 
 
2966
  ARGS
 
2967
 
 
2968
    check_if_ignore_table()
 
2969
    table_name                  Table name to check
 
2970
    table_type                  Type of table
 
2971
 
 
2972
  GLOBAL VARIABLES
 
2973
    drizzle                       Drizzle connection
 
2974
    verbose                     Write warning messages
 
2975
 
 
2976
  RETURN
 
2977
    char (bit value)            See IGNORE_ values at top
 
2978
*/
 
2979
 
 
2980
char check_if_ignore_table(const char *table_name, char *table_type)
 
2981
{
 
2982
  char result= IGNORE_NONE;
 
2983
  char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
 
2984
  const char *number_of_rows= NULL;
 
2985
  DRIZZLE_RES *res= NULL;
 
2986
  DRIZZLE_ROW row;
 
2987
 
 
2988
  /* Check memory for quote_for_like() */
 
2989
  assert(2*sizeof(table_name) < sizeof(show_name_buff));
 
2990
  snprintf(buff, sizeof(buff), "show table status like %s",
 
2991
           quote_for_like(table_name, show_name_buff));
 
2992
  if (drizzleclient_query_with_error_report(drizzle, &res, buff))
 
2993
  {
 
2994
    if (drizzleclient_errno(drizzle) != ER_PARSE_ERROR)
 
2995
    {                                   /* If old DRIZZLE version */
 
2996
      verbose_msg(_("-- Warning: Couldn't get status information for "
 
2997
                  "table %s (%s)\n"), table_name, drizzleclient_error(drizzle));
 
2998
      return(result);                       /* assume table is ok */
 
2999
    }
 
3000
  }
 
3001
  if (!(row= drizzleclient_fetch_row(res)))
 
3002
  {
 
3003
    fprintf(stderr,
 
3004
            _("Error: Couldn't read status information for table %s (%s)\n"),
 
3005
            table_name, drizzleclient_error(drizzle));
 
3006
    drizzleclient_free_result(res);
 
3007
    return(result);                         /* assume table is ok */
 
3008
  }
 
3009
  else
 
3010
  {
 
3011
    if ((number_of_rows= fetch_named_row(res, row, "Rows")) != NULL)
 
3012
    {
 
3013
      total_rows= strtoul(number_of_rows, NULL, 10);
 
3014
    }
 
3015
  }
 
3016
  /*
 
3017
    If the table type matches any of these, we do support delayed inserts.
 
3018
    Note: we do not want to skip dumping this table if if is not one of
 
3019
    these types, but we do want to use delayed inserts in the dump if
 
3020
    the table type is _NOT_ one of these types
 
3021
    */
 
3022
  {
 
3023
    strncpy(table_type, row[1], NAME_LEN-1);
 
3024
    if (opt_delayed)
 
3025
    {
 
3026
      if (strcmp(table_type,"MyISAM") &&
 
3027
          strcmp(table_type,"ARCHIVE") &&
 
3028
          strcmp(table_type,"HEAP") &&
 
3029
          strcmp(table_type,"MEMORY"))
 
3030
        result= IGNORE_INSERT_DELAYED;
 
3031
    }
 
3032
  }
 
3033
  drizzleclient_free_result(res);
 
3034
  return(result);
 
3035
}
 
3036
 
 
3037
 
 
3038
/*
 
3039
  Get string of comma-separated primary key field names
 
3040
 
 
3041
  SYNOPSIS
 
3042
    char *primary_key_fields(const char *table_name)
 
3043
    RETURNS     pointer to allocated buffer (must be freed by caller)
 
3044
    table_name  quoted table name
 
3045
 
 
3046
  DESCRIPTION
 
3047
    Use SHOW KEYS FROM table_name, allocate a buffer to hold the
 
3048
    field names, and then build that string and return the pointer
 
3049
    to that buffer.
 
3050
 
 
3051
    Returns NULL if there is no PRIMARY or UNIQUE key on the table,
 
3052
    or if there is some failure.  It is better to continue to dump
 
3053
    the table unsorted, rather than exit without dumping the data.
 
3054
*/
 
3055
 
 
3056
static char *primary_key_fields(const char *table_name)
 
3057
{
 
3058
  DRIZZLE_RES  *res= NULL;
 
3059
  DRIZZLE_ROW  row;
 
3060
  /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
 
3061
  char show_keys_buff[15 + NAME_LEN * 2 + 3];
 
3062
  uint32_t result_length= 0;
 
3063
  char *result= 0;
 
3064
  char buff[NAME_LEN * 2 + 3];
 
3065
  char *quoted_field;
 
3066
 
 
3067
  snprintf(show_keys_buff, sizeof(show_keys_buff),
 
3068
           "SHOW KEYS FROM %s", table_name);
 
3069
  if (drizzleclient_query(drizzle, show_keys_buff) ||
 
3070
      !(res= drizzleclient_store_result(drizzle)))
 
3071
  {
 
3072
    fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
3073
            " records are NOT sorted (%s)\n"),
 
3074
            table_name, drizzleclient_error(drizzle));
 
3075
    /* Don't exit, because it's better to print out unsorted records */
 
3076
    goto cleanup;
 
3077
  }
 
3078
 
 
3079
  /*
 
3080
   * Figure out the length of the ORDER BY clause result.
 
3081
   * Note that SHOW KEYS is ordered:  a PRIMARY key is always the first
 
3082
   * row, and UNIQUE keys come before others.  So we only need to check
 
3083
   * the first key, not all keys.
 
3084
   */
 
3085
  if ((row= drizzleclient_fetch_row(res)) && atoi(row[1]) == 0)
 
3086
  {
 
3087
    /* Key is unique */
 
3088
    do
 
3089
    {
 
3090
      quoted_field= quote_name(row[4], buff, 0);
 
3091
      result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
 
3092
    } while ((row= drizzleclient_fetch_row(res)) && atoi(row[3]) > 1);
 
3093
  }
 
3094
 
 
3095
  /* Build the ORDER BY clause result */
 
3096
  if (result_length)
 
3097
  {
 
3098
    char *end;
 
3099
    /* result (terminating \0 is already in result_length) */
 
3100
    result= (char *)malloc(result_length + 10);
 
3101
    if (!result)
 
3102
    {
 
3103
      fprintf(stderr, _("Error: Not enough memory to store ORDER BY clause\n"));
 
3104
      goto cleanup;
 
3105
    }
 
3106
    drizzleclient_data_seek(res, 0);
 
3107
    row= drizzleclient_fetch_row(res);
 
3108
    quoted_field= quote_name(row[4], buff, 0);
 
3109
    end= strcpy(result, quoted_field) + strlen(quoted_field);
 
3110
    while ((row= drizzleclient_fetch_row(res)) && atoi(row[3]) > 1)
 
3111
    {
 
3112
      quoted_field= quote_name(row[4], buff, 0);
 
3113
      end+= sprintf(end,",%s",quoted_field);
 
3114
    }
 
3115
  }
 
3116
 
 
3117
cleanup:
 
3118
  if (res)
 
3119
    drizzleclient_free_result(res);
 
3120
 
 
3121
  return result;
 
3122
}
 
3123
 
468
3124
 
469
3125
int main(int argc, char **argv)
470
3126
{
471
 
try
472
 
{
 
3127
  char bin_log_name[FN_REFLEN];
473
3128
  int exit_code;
474
 
 
475
 
  po::options_description commandline_options(N_("Options used only in command line"));
476
 
  commandline_options.add_options()
477
 
  ("all-databases,A", po::value<bool>(&opt_alldbs)->default_value(false)->zero_tokens(),
478
 
  N_("Dump all the databases. This will be same as --databases with all databases selected."))
479
 
  ("all-tablespaces,Y", po::value<bool>(&opt_alltspcs)->default_value(false)->zero_tokens(),
480
 
  N_("Dump all the tablespaces."))
481
 
  ("complete-insert,c", po::value<bool>(&opt_complete_insert)->default_value(false)->zero_tokens(),
482
 
  N_("Use complete insert statements."))
483
 
  ("flush-logs,F", po::value<bool>(&flush_logs)->default_value(false)->zero_tokens(),
484
 
  N_("Flush logs file in server before starting dump. Note that if you dump many databases at once (using the option --databases= or --all-databases), the logs will be flushed for each database dumped. The exception is when using --lock-all-tables in this case the logs will be flushed only once, corresponding to the moment all tables are locked. So if you want your dump and the log flush to happen at the same exact moment you should use --lock-all-tables or --flush-logs"))
485
 
  ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
486
 
  N_("Continue even if we get an sql-error."))
487
 
  ("help,?", N_("Display this help message and exit."))
488
 
  ("lock-all-tables,x", po::value<bool>(&opt_lock_all_tables)->default_value(false)->zero_tokens(),
489
 
  N_("Locks all tables across all databases. This is achieved by taking a global read lock for the duration of the whole dump. Automatically turns --single-transaction off."))
490
 
  ("single-transaction", po::value<bool>(&opt_single_transaction)->default_value(false)->zero_tokens(),
491
 
  N_("Creates a consistent snapshot by dumping all tables in a single transaction. Works ONLY for tables stored in storage engines which support multiversioning (currently only InnoDB does); the dump is NOT guaranteed to be consistent for other storage engines. While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents), no other connection should use the following statements: ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not isolated from them."))
492
 
  ("skip-opt", 
493
 
  N_("Disable --opt. Disables --add-drop-table, --add-locks, --create-options, ---extended-insert and --disable-keys."))    
494
 
  ("tables", N_("Overrides option --databases (-B)."))
495
 
  ("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(10000),
496
 
  N_("Number of rows before each output progress report (requires --verbose)."))
497
 
  ("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
498
 
  N_("Print info about the various stages."))
499
 
  ("version,V", N_("Output version information and exit."))
500
 
  ("skip-comments", N_("Turn off Comments"))
501
 
  ("skip-create", N_("Turn off create-options"))
502
 
  ("skip-extended-insert", N_("Turn off extended-insert"))
503
 
  ("skip-dump-date",N_( "Turn off dump date at the end of the output"))
504
 
  ("no-defaults", N_("Do not read from the configuration files"))
505
 
  ;
506
 
 
507
 
  po::options_description dump_options(N_("Options specific to the drizzle client"));
508
 
  dump_options.add_options()
509
 
  ("add-drop-database", po::value<bool>(&opt_drop_database)->default_value(false)->zero_tokens(),
510
 
  N_("Add a 'DROP DATABASE' before each create."))
511
 
  ("skip-drop-table", N_("Do not add a 'drop table' before each create."))
512
 
  ("compact", po::value<bool>(&opt_compact)->default_value(false)->zero_tokens(),
513
 
  N_("Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs.  Enables options --skip-add-drop-table --no-set-names --skip-disable-keys"))
514
 
  ("databases,B", po::value<bool>(&opt_databases)->default_value(false)->zero_tokens(),
515
 
  N_("To dump several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames. 'USE db_name;' will be included in the output."))
516
 
  ("skip-disable-keys,K",
517
 
  N_("'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will not be put in the output."))
518
 
  ("ignore-table", po::value<string>(),
519
 
  N_("Do not dump the specified table. To specify more than one table to ignore, use the directive multiple times, once for each table.  Each table must be specified with both database and table names, e.g. --ignore-table=database.table"))
520
 
  ("insert-ignore", po::value<bool>(&opt_ignore)->default_value(false)->zero_tokens(),
521
 
  N_("Insert rows with INSERT IGNORE."))
522
 
  ("no-autocommit", po::value<bool>(&opt_autocommit)->default_value(false)->zero_tokens(),
523
 
  N_("Wrap a table's data in START TRANSACTION/COMMIT statements."))
524
 
  ("no-create-db,n", po::value<bool>(&opt_create_db)->default_value(false)->zero_tokens(),
525
 
  N_("'CREATE DATABASE IF NOT EXISTS db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given."))
526
 
  ("no-data,d", po::value<bool>(&opt_no_data)->default_value(false)->zero_tokens(),
527
 
  N_("No row information."))
528
 
  ("replace", po::value<bool>(&opt_replace_into)->default_value(false)->zero_tokens(),
529
 
  N_("Use REPLACE INTO instead of INSERT INTO."))
530
 
  ("destination-type", po::value<string>()->default_value("stdout"),
531
 
  N_("Where to send output to (stdout|database"))
532
 
  ("destination-host", po::value<string>(&opt_destination_host)->default_value("localhost"),
533
 
  N_("Hostname for destination db server (requires --destination-type=database)"))
534
 
  ("destination-port", po::value<uint16_t>(&opt_destination_port)->default_value(4427),
535
 
  N_("Port number for destination db server (requires --destination-type=database)"))
536
 
  ("destination-user", po::value<string>(&opt_destination_user),
537
 
  N_("User name for destination db server (resquires --destination-type=database)"))
538
 
  ("destination-password", po::value<string>(&opt_destination_password),
539
 
  N_("Password for destination db server (requires --destination-type=database)"))
540
 
  ("destination-database", po::value<string>(&opt_destination_database),
541
 
  N_("The database in the destination db server (requires --destination-type=database, not for use with --all-databases)"))
542
 
  ;
543
 
 
544
 
  po::options_description client_options(N_("Options specific to the client"));
545
 
  client_options.add_options()
546
 
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
547
 
  N_("Connect to host."))
548
 
  ("password,P", po::value<string>(&password)->default_value(PASSWORD_SENTINEL),
549
 
  N_("Password to use when connecting to server. If password is not given it's solicited on the tty."))
550
 
  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
551
 
  N_("Port number to use for connection."))
552
 
  ("user,u", po::value<string>(&current_user)->default_value(""),
553
 
  N_("User for login if not current user."))
554
 
  ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
555
 
  N_("The protocol of connection (mysql or drizzle)."))
556
 
  ;
557
 
 
558
 
  po::options_description hidden_options(N_("Hidden Options"));
559
 
  hidden_options.add_options()
560
 
  ("database-used", po::value<vector<string> >(), N_("Used to select the database"))
561
 
  ("Table-used", po::value<vector<string> >(), N_("Used to select the tables"))
562
 
  ;
563
 
 
564
 
  po::options_description all_options(N_("Allowed Options + Hidden Options"));
565
 
  all_options.add(commandline_options).add(dump_options).add(client_options).add(hidden_options);
566
 
 
567
 
  po::options_description long_options(N_("Allowed Options"));
568
 
  long_options.add(commandline_options).add(dump_options).add(client_options);
569
 
 
570
 
  std::string system_config_dir_dump(SYSCONFDIR); 
571
 
  system_config_dir_dump.append("/drizzle/drizzledump.cnf");
572
 
 
573
 
  std::string system_config_dir_client(SYSCONFDIR); 
574
 
  system_config_dir_client.append("/drizzle/client.cnf");
575
 
 
576
 
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
577
 
 
578
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
579
 
  {
580
 
    char *homedir;
581
 
    homedir= getenv("HOME");
582
 
    if (homedir != NULL)
583
 
      user_config_dir.replace(0, 1, homedir);
584
 
  }
585
 
 
586
 
  po::positional_options_description p;
587
 
  p.add("database-used", 1);
588
 
  p.add("Table-used",-1);
589
 
 
590
 
  md_result_file= stdout;
591
 
 
592
 
  po::variables_map vm;
593
 
 
594
 
  // Disable allow_guessing
595
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
596
 
 
597
 
  po::store(po::command_line_parser(argc, argv).style(style).
598
 
            options(all_options).positional(p).
599
 
            extra_parser(parse_password_arg).run(), vm);
600
 
 
601
 
  if (! vm.count("no-defaults"))
602
 
  {
603
 
    std::string user_config_dir_dump(user_config_dir);
604
 
    user_config_dir_dump.append("/drizzle/drizzledump.cnf"); 
605
 
 
606
 
    std::string user_config_dir_client(user_config_dir);
607
 
    user_config_dir_client.append("/drizzle/client.cnf");
608
 
 
609
 
    ifstream user_dump_ifs(user_config_dir_dump.c_str());
610
 
    po::store(parse_config_file(user_dump_ifs, dump_options), vm);
611
 
 
612
 
    ifstream user_client_ifs(user_config_dir_client.c_str());
613
 
    po::store(parse_config_file(user_client_ifs, client_options), vm);
614
 
 
615
 
    ifstream system_dump_ifs(system_config_dir_dump.c_str());
616
 
    po::store(parse_config_file(system_dump_ifs, dump_options), vm);
617
 
 
618
 
    ifstream system_client_ifs(system_config_dir_client.c_str());
619
 
    po::store(parse_config_file(system_client_ifs, client_options), vm);
620
 
  }
621
 
 
622
 
  po::notify(vm);  
623
 
  
624
 
  if ((not vm.count("database-used") && not vm.count("Table-used") 
625
 
    && not opt_alldbs && path.empty())
626
 
    || (vm.count("help")) || vm.count("version"))
627
 
  {
628
 
    printf(_("Drizzledump %s build %s, for %s-%s (%s)\n"),
629
 
      drizzle_version(), VERSION, HOST_VENDOR, HOST_OS, HOST_CPU);
630
 
    if (vm.count("version"))
631
 
      exit(0);
632
 
    puts("");
633
 
    puts(_("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"));
634
 
    puts(_("Dumps definitions and data from a Drizzle database server"));
635
 
    printf(_("Usage: %s [OPTIONS] database [tables]\n"), progname.c_str());
636
 
    printf(_("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n"),
637
 
          progname.c_str());
638
 
    printf(_("OR     %s [OPTIONS] --all-databases [OPTIONS]\n"), progname.c_str());
639
 
    cout << long_options;
640
 
    if (vm.count("help"))
641
 
      exit(0);
642
 
    else
643
 
      exit(1);
644
 
  }
645
 
 
646
 
  /* Inverted Booleans */
647
 
 
648
 
  opt_drop= (vm.count("skip-drop-table")) ? false : true;
649
 
  opt_comments= (vm.count("skip-comments")) ? false : true;
650
 
  extended_insert= (vm.count("skip-extended-insert")) ? false : true;
651
 
  opt_dump_date= (vm.count("skip-dump-date")) ? false : true;
652
 
  opt_disable_keys= (vm.count("skip-disable-keys")) ? false : true;
653
 
  opt_quoted= (vm.count("skip-quote-names")) ? false : true;
654
 
 
655
 
  if (vm.count("protocol"))
656
 
  {
657
 
    std::transform(opt_protocol.begin(), opt_protocol.end(),
658
 
      opt_protocol.begin(), ::tolower);
659
 
 
660
 
    if (not opt_protocol.compare("mysql"))
661
 
      use_drizzle_protocol=false;
662
 
    else if (not opt_protocol.compare("drizzle"))
663
 
      use_drizzle_protocol=true;
664
 
    else
665
 
    {
666
 
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
667
 
      exit(-1);
668
 
    }
669
 
  }
670
 
 
671
 
  if (vm.count("port"))
672
 
  {
673
 
    /* If the port number is > 65535 it is not a valid port
674
 
     *        This also helps with potential data loss casting unsigned long to a
675
 
     *               uint32_t. 
676
 
     */
677
 
    if (opt_drizzle_port > 65535)
678
 
    {
679
 
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
680
 
      exit(-1);
681
 
    }
682
 
  }
683
 
 
684
 
  if(vm.count("password"))
685
 
  {
686
 
    if (!opt_password.empty())
687
 
      opt_password.erase();
688
 
    if (password == PASSWORD_SENTINEL)
689
 
    {
690
 
      opt_password= "";
691
 
    }
692
 
    else
693
 
    {
694
 
      opt_password= password;
695
 
      tty_password= false;
696
 
    }
697
 
  }
698
 
  else
699
 
  {
700
 
      tty_password= true;
701
 
  }
702
 
 
703
 
  if (! path.empty())
704
 
  { 
705
 
    opt_disable_keys= 0;
706
 
  }
707
 
 
708
 
  if (vm.count("skip-opt"))
709
 
  {
710
 
    extended_insert= opt_drop= create_options= 0;
711
 
    opt_disable_keys= 0;
712
 
  }
713
 
 
714
 
  if (opt_compact)
715
 
  { 
716
 
    opt_comments= opt_drop= opt_disable_keys= 0;
717
 
  }
718
 
 
719
 
  if (vm.count("opt"))
720
 
  {
721
 
    extended_insert= opt_drop= create_options= 1;
722
 
    opt_disable_keys= 1;
723
 
  }
724
 
 
725
 
  if (vm.count("tables"))
726
 
  { 
727
 
    opt_databases= false;
728
 
  }
729
 
 
730
 
  if (vm.count("ignore-table"))
731
 
  {
732
 
    if (!strchr(vm["ignore-table"].as<string>().c_str(), '.'))
733
 
    {
734
 
      fprintf(stderr, _("Illegal use of option --ignore-table=<database>.<table>\n"));
735
 
      exit(EXIT_ARGUMENT_INVALID);
736
 
    }
737
 
    string tmpptr(vm["ignore-table"].as<string>());
738
 
    ignore_table.insert(tmpptr); 
739
 
  }
740
 
 
741
 
  if (vm.count("skip-create"))
742
 
  {
743
 
    opt_create_db= opt_no_create_info= create_options= false;
744
 
  }
745
 
 
746
 
  exit_code= get_options();
 
3129
  MY_INIT("drizzledump");
 
3130
 
 
3131
  compatible_mode_normal_str[0]= 0;
 
3132
  default_charset= (char *)drizzle_universal_client_charset;
 
3133
  memset(&ignore_table, 0, sizeof(ignore_table));
 
3134
 
 
3135
  exit_code= get_options(&argc, &argv);
747
3136
  if (exit_code)
748
3137
  {
749
3138
    free_resources();
750
3139
    exit(exit_code);
751
3140
  }
752
 
  try
753
 
  {
754
 
    db_connection = new DrizzleDumpConnection(current_host, opt_drizzle_port,
755
 
      current_user, opt_password, use_drizzle_protocol);
756
 
  }
757
 
  catch (std::exception&)
758
 
  {
759
 
    maybe_exit(EX_DRIZZLEERR);
760
 
  }
761
 
 
762
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
763
 
    db_connection->queryNoResult("SET NAMES 'utf8'");
764
 
 
765
 
  if (vm.count("destination-type"))
766
 
  {
767
 
    string tmp_destination(vm["destination-type"].as<string>());
768
 
    if (tmp_destination.compare("database") == 0)
769
 
      opt_destination= DESTINATION_DB;
770
 
    else if (tmp_destination.compare("stdout") == 0)
771
 
      opt_destination= DESTINATION_STDOUT;
772
 
    else
773
 
      exit(EXIT_ARGUMENT_INVALID);
774
 
  }
775
 
 
776
 
 
777
 
  if (path.empty() && vm.count("database-used"))
778
 
  {
779
 
    string database_used= *vm["database-used"].as< vector<string> >().begin();
780
 
    write_header((char *)database_used.c_str());
781
 
  }
782
 
 
783
 
  if ((opt_lock_all_tables) && do_flush_tables_read_lock())
784
 
    goto err;
785
 
  if (opt_single_transaction && start_transaction())
786
 
    goto err;
787
 
  if (opt_lock_all_tables)
788
 
    db_connection->queryNoResult("FLUSH LOGS");
789
 
  if (opt_single_transaction && do_unlock_tables()) /* unlock but no commit! */
 
3141
 
 
3142
  if (connect_to_db(current_host, current_user, opt_password))
 
3143
  {
 
3144
    free_resources();
 
3145
    exit(EX_DRIZZLEERR);
 
3146
  }
 
3147
  if (!path)
 
3148
    write_header(md_result_file, *argv);
 
3149
 
 
3150
  if (opt_slave_data && do_stop_slave_sql(drizzle))
 
3151
    goto err;
 
3152
 
 
3153
  if ((opt_lock_all_tables || opt_master_data) &&
 
3154
      do_flush_tables_read_lock(drizzle))
 
3155
    goto err;
 
3156
  if (opt_single_transaction && start_transaction(drizzle))
 
3157
      goto err;
 
3158
  if (opt_delete_master_logs)
 
3159
  {
 
3160
    if (drizzleclient_refresh(drizzle, REFRESH_LOG) ||
 
3161
        get_bin_log_name(drizzle, bin_log_name, sizeof(bin_log_name)))
 
3162
      goto err;
 
3163
    flush_logs= 0;
 
3164
  }
 
3165
  if (opt_lock_all_tables || opt_master_data)
 
3166
  {
 
3167
    if (flush_logs && drizzleclient_refresh(drizzle, REFRESH_LOG))
 
3168
      goto err;
 
3169
    flush_logs= 0; /* not anymore; that would not be sensible */
 
3170
  }
 
3171
  /* Add 'STOP SLAVE to beginning of dump */
 
3172
  if (opt_slave_apply && add_stop_slave())
 
3173
    goto err;
 
3174
  if (opt_master_data && do_show_master_status(drizzle))
 
3175
    goto err;
 
3176
  if (opt_slave_data && do_show_slave_status(drizzle))
 
3177
    goto err;
 
3178
  if (opt_single_transaction && do_unlock_tables(drizzle)) /* unlock but no commit! */
790
3179
    goto err;
791
3180
 
792
3181
  if (opt_alldbs)
793
3182
  {
794
3183
    dump_all_databases();
795
 
    dump_all_tables();
796
3184
  }
797
 
  if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
 
3185
  else if (argc > 1 && !opt_databases)
798
3186
  {
799
 
    string database_used= *vm["database-used"].as< vector<string> >().begin();
800
3187
    /* Only one database and selected table(s) */
801
 
    dump_selected_tables(database_used, vm["Table-used"].as< vector<string> >());
802
 
  }
803
 
 
804
 
  if (vm.count("Table-used") and opt_databases)
805
 
  {
806
 
    vector<string> database_used= vm["database-used"].as< vector<string> >();
807
 
    vector<string> table_used= vm["Table-used"].as< vector<string> >();
808
 
 
809
 
    for (vector<string>::iterator it= table_used.begin();
810
 
       it != table_used.end();
811
 
       ++it)
812
 
    {
813
 
      database_used.insert(database_used.end(), *it);
814
 
    }
815
 
 
816
 
    dump_databases(database_used);
817
 
    dump_all_tables();
818
 
  }
819
 
 
820
 
  if (vm.count("database-used") && ! vm.count("Table-used"))
821
 
  {
822
 
    dump_databases(vm["database-used"].as< vector<string> >());
823
 
    dump_all_tables();
824
 
  }
825
 
 
826
 
  if (opt_destination == DESTINATION_STDOUT)
827
 
    generate_dump();
 
3188
    dump_selected_tables(*argv, (argv + 1), (argc - 1));
 
3189
  }
828
3190
  else
829
 
    generate_dump_db();
 
3191
  {
 
3192
    dump_databases(argv);
 
3193
  }
 
3194
 
 
3195
  /* if --dump-slave , start the slave sql thread */
 
3196
  if (opt_slave_data && do_start_slave_sql(drizzle))
 
3197
    goto err;
 
3198
 
 
3199
  /* add 'START SLAVE' to end of dump */
 
3200
  if (opt_slave_apply && add_slave_statements())
 
3201
    goto err;
830
3202
 
831
3203
  /* ensure dumped data flushed */
832
3204
  if (md_result_file && fflush(md_result_file))
835
3207
      first_error= EX_DRIZZLEERR;
836
3208
    goto err;
837
3209
  }
 
3210
  /* everything successful, purge the old logs files */
 
3211
  if (opt_delete_master_logs && purge_bin_logs_to(drizzle, bin_log_name))
 
3212
    goto err;
838
3213
 
839
3214
  /*
840
3215
    No reason to explicitely COMMIT the transaction, neither to explicitely
843
3218
    server.
844
3219
  */
845
3220
err:
846
 
  delete db_connection;
847
 
  delete destination_connection;
848
 
  if (path.empty())
 
3221
  dbDisconnect(current_host);
 
3222
  if (!path)
849
3223
    write_footer(md_result_file);
850
3224
  free_resources();
851
3225
 
852
3226
  if (stderror_file)
853
3227
    fclose(stderror_file);
854
 
}
855
3228
 
856
 
  catch(exception &err)
857
 
  {
858
 
    cerr << err.what() << endl;
859
 
  }
860
 
  
861
3229
  return(first_error);
862
3230
} /* main */