~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Brian Aker
  • Date: 2009-05-30 22:30:05 UTC
  • mto: This revision was merged to the branch mainline in revision 1045.
  • Revision ID: brian@gaz-20090530223005-hmylm6iywddfentm
A lot of little cleanups (most based off lcov)

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