~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Monty Taylor
  • Date: 2009-03-06 03:33:24 UTC
  • mfrom: (916.1.2 merge)
  • Revision ID: mordred@inaugust.com-20090306033324-dcedf80g9qzywbvu
Merged Brian's merge... re-rotate the tree.

Show diffs side-by-side

added added

removed removed

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