~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Monty Taylor
  • Date: 2009-02-08 11:28:58 UTC
  • mto: This revision was merged to the branch mainline in revision 852.
  • Revision ID: mordred@inaugust.com-20090208112858-aouo9w2okht5r6x0
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.

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