~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Brian Aker
  • Date: 2009-04-27 14:36:40 UTC
  • Revision ID: brian@gaz-20090427143640-f6zjmtt9vm55qgm2
Patch on show processlist from  davi@apache.org

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
const char *default_dbug_option="d:t:o,/tmp/drizzledump.trace";
 
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));
 
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 %s"),
 
854
              drizzle_result_error_code(res), when);
 
855
    drizzle_result_free(res);
 
856
  }
 
857
  else
 
858
    maybe_die(EX_DRIZZLEERR, _("Got error: %s %s"), ret, when);
 
859
 
 
860
  return;
 
861
}
 
862
 
 
863
 
 
864
 
 
865
/*
318
866
  Prints out an error message and kills the process.
319
867
 
320
868
  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
 
869
    die()
 
870
    error_num   - process return value
 
871
    fmt_reason  - a format string for use by vsnprintf.
 
872
    ...         - variable arguments for above fmt_reason string
325
873
 
326
874
  DESCRIPTION
327
 
  This call prints out the formatted error message to stderr and then
328
 
  terminates the process.
 
875
    This call prints out the formatted error message to stderr and then
 
876
    terminates the process.
329
877
*/
330
878
static void die(int error_num, const char* fmt_reason, ...)
331
879
{
335
883
  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
336
884
  va_end(args);
337
885
 
338
 
  fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
 
886
  fprintf(stderr, "%s: %s\n", my_progname, buffer);
339
887
  fflush(stderr);
340
888
 
341
889
  ignore_errors= 0; /* force the exit */
342
890
  maybe_exit(error_num);
343
891
}
344
892
 
 
893
 
 
894
/*
 
895
  Prints out an error message and maybe kills the process.
 
896
 
 
897
  SYNOPSIS
 
898
    maybe_die()
 
899
    error_num   - process return value
 
900
    fmt_reason  - a format string for use by vsnprintf.
 
901
    ...         - variable arguments for above fmt_reason string
 
902
 
 
903
  DESCRIPTION
 
904
    This call prints out the formatted error message to stderr and then
 
905
    terminates the process, unless the --force command line option is used.
 
906
 
 
907
    This call should be used for non-fatal errors (such as database
 
908
    errors) that the code may still be able to continue to the next unit
 
909
    of work.
 
910
 
 
911
*/
 
912
static void maybe_die(int error_num, const char* fmt_reason, ...)
 
913
{
 
914
  char buffer[1000];
 
915
  va_list args;
 
916
  va_start(args,fmt_reason);
 
917
  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
 
918
  va_end(args);
 
919
 
 
920
  fprintf(stderr, "%s: %s\n", my_progname, buffer);
 
921
  fflush(stderr);
 
922
 
 
923
  maybe_exit(error_num);
 
924
}
 
925
 
 
926
 
 
927
 
 
928
/*
 
929
  Sends a query to server, optionally reads result, prints error message if
 
930
  some.
 
931
 
 
932
  SYNOPSIS
 
933
    drizzleclient_query_with_error_report()
 
934
    drizzle_con       connection to use
 
935
    res             if non zero, result will be put there with
 
936
                    drizzleclient_store_result()
 
937
    query           query to send to server
 
938
 
 
939
  RETURN VALUES
 
940
    0               query sending and (if res!=0) result reading went ok
 
941
    1               error
 
942
*/
 
943
 
 
944
static int drizzleclient_query_with_error_report(drizzle_con_st *con,
 
945
                                                 drizzle_result_st *result,
 
946
                                                 const char *query_str,
 
947
                                                 bool no_buffer)
 
948
{
 
949
  drizzle_return_t ret;
 
950
 
 
951
  if (drizzle_query_str(con, result, query_str, &ret) == NULL ||
 
952
      ret != DRIZZLE_RETURN_OK)
 
953
  {
 
954
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
955
    {
 
956
      maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
957
                query_str, drizzle_result_error(result),
 
958
                drizzle_result_error_code(result));
 
959
      drizzle_result_free(result);
 
960
    }
 
961
    else
 
962
    {
 
963
      maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
964
                query_str, drizzle_con_error(con), ret);
 
965
    }
 
966
    return 1;
 
967
  }
 
968
 
 
969
  if (no_buffer)
 
970
    ret= drizzle_column_buffer(result);
 
971
  else
 
972
    ret= drizzle_result_buffer(result);
 
973
  if (ret != DRIZZLE_RETURN_OK)
 
974
  {
 
975
    drizzle_result_free(result);
 
976
    maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
977
              query_str, drizzle_con_error(con), ret);
 
978
    return 1;
 
979
  }
 
980
 
 
981
  return 0;
 
982
}
 
983
 
 
984
/*
 
985
  Open a new .sql file to dump the table or view into
 
986
 
 
987
  SYNOPSIS
 
988
    open_sql_file_for_table
 
989
    name      name of the table or view
 
990
 
 
991
  RETURN VALUES
 
992
    0        Failed to open file
 
993
    > 0      Handle of the open file
 
994
*/
 
995
static FILE* open_sql_file_for_table(const char* table)
 
996
{
 
997
  FILE* res;
 
998
  char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
999
  convert_dirname(tmp_path,path,NULL);
 
1000
  res= fopen(fn_format(filename, table, tmp_path, ".sql", 4), "w");
 
1001
 
 
1002
  return res;
 
1003
}
 
1004
 
 
1005
 
345
1006
static void free_resources(void)
346
1007
{
347
1008
  if (md_result_file && md_result_file != stdout)
348
1009
    fclose(md_result_file);
349
 
  opt_password.erase();
 
1010
  free(opt_password);
 
1011
  if (hash_inited(&ignore_table))
 
1012
    hash_free(&ignore_table);
 
1013
  if (defaults_argv)
 
1014
    free_defaults(defaults_argv);
 
1015
  my_end(my_end_arg);
350
1016
}
351
1017
 
352
1018
 
353
 
void maybe_exit(int error)
 
1019
static void maybe_exit(int error)
354
1020
{
355
1021
  if (!first_error)
356
1022
    first_error= error;
357
1023
  if (ignore_errors)
358
1024
    return;
359
 
  delete db_connection;
360
 
  delete destination_connection;
 
1025
  drizzle_con_free(&dcon);
 
1026
  drizzle_free(&drizzle);
361
1027
  free_resources();
362
1028
  exit(error);
363
1029
}
364
1030
 
 
1031
 
 
1032
/*
 
1033
  db_connect -- connects to the host and selects DB.
 
1034
*/
 
1035
 
 
1036
static int connect_to_db(char *host, char *user,char *passwd)
 
1037
{
 
1038
  drizzle_return_t ret;
 
1039
 
 
1040
  verbose_msg(_("-- Connecting to %s...\n"), host ? host : "localhost");
 
1041
  drizzle_create(&drizzle);
 
1042
  drizzle_con_create(&drizzle, &dcon);
 
1043
  drizzle_con_set_tcp(&dcon, host, opt_drizzle_port);
 
1044
  drizzle_con_set_auth(&dcon, user, passwd);
 
1045
  ret= drizzle_con_connect(&dcon);
 
1046
  if (ret != DRIZZLE_RETURN_OK)
 
1047
  {
 
1048
    DB_error(NULL, ret, "when trying to connect");
 
1049
    return(1);
 
1050
  }
 
1051
 
 
1052
  return(0);
 
1053
} /* connect_to_db */
 
1054
 
 
1055
 
 
1056
/*
 
1057
** dbDisconnect -- disconnects from the host.
 
1058
*/
 
1059
static void dbDisconnect(char *host)
 
1060
{
 
1061
  verbose_msg(_("-- Disconnecting from %s...\n"), host ? host : "localhost");
 
1062
  drizzle_con_free(&dcon);
 
1063
  drizzle_free(&drizzle);
 
1064
} /* dbDisconnect */
 
1065
 
 
1066
 
 
1067
static void unescape(FILE *file,char *pos,uint32_t length)
 
1068
{
 
1069
  char *tmp;
 
1070
 
 
1071
  if (!(tmp=(char*) malloc(length*2+1)))
 
1072
    die(EX_DRIZZLEERR, _("Couldn't allocate memory"));
 
1073
 
 
1074
  drizzle_escape_string(tmp, pos, length);
 
1075
  fputc('\'', file);
 
1076
  fputs(tmp, file);
 
1077
  fputc('\'', file);
 
1078
  check_io(file);
 
1079
  free(tmp);
 
1080
  return;
 
1081
} /* unescape */
 
1082
 
 
1083
 
 
1084
static bool test_if_special_chars(const char *str)
 
1085
{
 
1086
  for ( ; *str ; str++)
 
1087
    if (!my_isvar(charset_info,*str) && *str != '$')
 
1088
      return 1;
 
1089
  return 0;
 
1090
} /* test_if_special_chars */
 
1091
 
 
1092
 
 
1093
 
 
1094
/*
 
1095
  quote_name(name, buff, force)
 
1096
 
 
1097
  Quotes char string, taking into account compatible mode
 
1098
 
 
1099
  Args
 
1100
 
 
1101
  name                 Unquoted string containing that which will be quoted
 
1102
  buff                 The buffer that contains the quoted value, also returned
 
1103
  force                Flag to make it ignore 'test_if_special_chars'
 
1104
 
 
1105
  Returns
 
1106
 
 
1107
  buff                 quoted string
 
1108
 
 
1109
*/
 
1110
static char *quote_name(const char *name, char *buff, bool force)
 
1111
{
 
1112
  char *to= buff;
 
1113
  char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';
 
1114
 
 
1115
  if (!force && !opt_quoted && !test_if_special_chars(name))
 
1116
    return (char*) name;
 
1117
  *to++= qtype;
 
1118
  while (*name)
 
1119
  {
 
1120
    if (*name == qtype)
 
1121
      *to++= qtype;
 
1122
    *to++= *name++;
 
1123
  }
 
1124
  to[0]= qtype;
 
1125
  to[1]= 0;
 
1126
  return buff;
 
1127
} /* quote_name */
 
1128
 
 
1129
 
 
1130
/*
 
1131
  Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
 
1132
 
 
1133
  SYNOPSIS
 
1134
    quote_for_like()
 
1135
    name     name of the table
 
1136
    buff     quoted name of the table
 
1137
 
 
1138
  DESCRIPTION
 
1139
    Quote \, _, ' and % characters
 
1140
 
 
1141
    Note: Because DRIZZLE uses the C escape syntax in strings
 
1142
    (for example, '\n' to represent newline), you must double
 
1143
    any '\' that you use in your LIKE  strings. For example, to
 
1144
    search for '\n', specify it as '\\n'. To search for '\', specify
 
1145
    it as '\\\\' (the backslashes are stripped once by the parser
 
1146
    and another time when the pattern match is done, leaving a
 
1147
    single backslash to be matched).
 
1148
 
 
1149
    Example: "t\1" => "t\\\\1"
 
1150
 
 
1151
*/
 
1152
static char *quote_for_like(const char *name, char *buff)
 
1153
{
 
1154
  char *to= buff;
 
1155
  *to++= '\'';
 
1156
  while (*name)
 
1157
  {
 
1158
    if (*name == '\\')
 
1159
    {
 
1160
      *to++='\\';
 
1161
      *to++='\\';
 
1162
      *to++='\\';
 
1163
    }
 
1164
    else if (*name == '\'' || *name == '_'  || *name == '%')
 
1165
      *to++= '\\';
 
1166
    *to++= *name++;
 
1167
  }
 
1168
  to[0]= '\'';
 
1169
  to[1]= 0;
 
1170
  return buff;
 
1171
}
 
1172
 
 
1173
 
 
1174
/*
 
1175
  Quote and print a string.
 
1176
 
 
1177
  SYNOPSIS
 
1178
    print_quoted_xml()
 
1179
    xml_file    - output file
 
1180
    str         - string to print
 
1181
    len         - its length
 
1182
 
 
1183
  DESCRIPTION
 
1184
    Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
 
1185
*/
 
1186
 
 
1187
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
 
1188
{
 
1189
  const char *end;
 
1190
 
 
1191
  for (end= str + len; str != end; str++)
 
1192
  {
 
1193
    switch (*str) {
 
1194
    case '<':
 
1195
      fputs("&lt;", xml_file);
 
1196
      break;
 
1197
    case '>':
 
1198
      fputs("&gt;", xml_file);
 
1199
      break;
 
1200
    case '&':
 
1201
      fputs("&amp;", xml_file);
 
1202
      break;
 
1203
    case '\"':
 
1204
      fputs("&quot;", xml_file);
 
1205
      break;
 
1206
    default:
 
1207
      fputc(*str, xml_file);
 
1208
      break;
 
1209
    }
 
1210
  }
 
1211
  check_io(xml_file);
 
1212
}
 
1213
 
 
1214
 
 
1215
/*
 
1216
  Print xml tag. Optionally add attribute(s).
 
1217
 
 
1218
  SYNOPSIS
 
1219
    print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
 
1220
                    ..., attribute_name_n, attribute_value_n, NULL)
 
1221
    xml_file              - output file
 
1222
    sbeg                  - line beginning
 
1223
    line_end              - line ending
 
1224
    tag_name              - XML tag name.
 
1225
    first_attribute_name  - tag and first attribute
 
1226
    first_attribute_value - (Implied) value of first attribute
 
1227
    attribute_name_n      - attribute n
 
1228
    attribute_value_n     - value of attribute n
 
1229
 
 
1230
  DESCRIPTION
 
1231
    Print XML tag with any number of attribute="value" pairs to the xml_file.
 
1232
 
 
1233
    Format is:
 
1234
      sbeg<tag_name first_attribute_name="first_attribute_value" ...
 
1235
      attribute_name_n="attribute_value_n">send
 
1236
  NOTE
 
1237
    Additional arguments must be present in attribute/value pairs.
 
1238
    The last argument should be the null character pointer.
 
1239
    All attribute_value arguments MUST be NULL terminated strings.
 
1240
    All attribute_value arguments will be quoted before output.
 
1241
*/
 
1242
 
 
1243
static void print_xml_tag(FILE * xml_file, const char* sbeg,
 
1244
                          const char* line_end,
 
1245
                          const char* tag_name,
 
1246
                          const char* first_attribute_name, ...)
 
1247
{
 
1248
  va_list arg_list;
 
1249
  const char *attribute_name, *attribute_value;
 
1250
 
 
1251
  fputs(sbeg, xml_file);
 
1252
  fputc('<', xml_file);
 
1253
  fputs(tag_name, xml_file);
 
1254
 
 
1255
  va_start(arg_list, first_attribute_name);
 
1256
  attribute_name= first_attribute_name;
 
1257
  while (attribute_name != NULL)
 
1258
  {
 
1259
    attribute_value= va_arg(arg_list, char *);
 
1260
    assert(attribute_value != NULL);
 
1261
 
 
1262
    fputc(' ', xml_file);
 
1263
    fputs(attribute_name, xml_file);
 
1264
    fputc('\"', xml_file);
 
1265
 
 
1266
    print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
 
1267
    fputc('\"', xml_file);
 
1268
 
 
1269
    attribute_name= va_arg(arg_list, char *);
 
1270
  }
 
1271
  va_end(arg_list);
 
1272
 
 
1273
  fputc('>', xml_file);
 
1274
  fputs(line_end, xml_file);
 
1275
  check_io(xml_file);
 
1276
}
 
1277
 
 
1278
 
 
1279
/*
 
1280
  Print xml tag with for a field that is null
 
1281
 
 
1282
  SYNOPSIS
 
1283
    print_xml_null_tag()
 
1284
    xml_file    - output file
 
1285
    sbeg        - line beginning
 
1286
    stag_atr    - tag and attribute
 
1287
    sval        - value of attribute
 
1288
    line_end        - line ending
 
1289
 
 
1290
  DESCRIPTION
 
1291
    Print tag with one attribute to the xml_file. Format is:
 
1292
      <stag_atr="sval" xsi:nil="true"/>
 
1293
  NOTE
 
1294
    sval MUST be a NULL terminated string.
 
1295
    sval string will be qouted before output.
 
1296
*/
 
1297
 
 
1298
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
 
1299
                               const char* stag_atr, const char* sval,
 
1300
                               const char* line_end)
 
1301
{
 
1302
  fputs(sbeg, xml_file);
 
1303
  fputs("<", xml_file);
 
1304
  fputs(stag_atr, xml_file);
 
1305
  fputs("\"", xml_file);
 
1306
  print_quoted_xml(xml_file, sval, strlen(sval));
 
1307
  fputs("\" xsi:nil=\"true\" />", xml_file);
 
1308
  fputs(line_end, xml_file);
 
1309
  check_io(xml_file);
 
1310
}
 
1311
 
 
1312
 
 
1313
/*
 
1314
  Print xml tag with many attributes.
 
1315
 
 
1316
  SYNOPSIS
 
1317
    print_xml_row()
 
1318
    xml_file    - output file
 
1319
    row_name    - xml tag name
 
1320
    tableRes    - query result
 
1321
    row         - result row
 
1322
 
 
1323
  DESCRIPTION
 
1324
    Print tag with many attribute to the xml_file. Format is:
 
1325
      \t\t<row_name Atr1="Val1" Atr2="Val2"... />
 
1326
  NOTE
 
1327
    All atributes and values will be quoted before output.
 
1328
*/
 
1329
 
 
1330
static void print_xml_row(FILE *xml_file, const char *row_name,
 
1331
                          drizzle_result_st *tableRes, drizzle_row_t *row)
 
1332
{
 
1333
  uint32_t i;
 
1334
  drizzle_column_st *column;
 
1335
  size_t *lengths= drizzle_row_field_sizes(tableRes);
 
1336
 
 
1337
  fprintf(xml_file, "\t\t<%s", row_name);
 
1338
  check_io(xml_file);
 
1339
  drizzle_column_seek(tableRes, 0);
 
1340
  for (i= 0; (column= drizzle_column_next(tableRes)); i++)
 
1341
  {
 
1342
    if ((*row)[i])
 
1343
    {
 
1344
      fputc(' ', xml_file);
 
1345
      print_quoted_xml(xml_file, drizzle_column_name(column),
 
1346
                       strlen(drizzle_column_name(column)));
 
1347
      fputs("=\"", xml_file);
 
1348
      print_quoted_xml(xml_file, (*row)[i], lengths[i]);
 
1349
      fputc('"', xml_file);
 
1350
      check_io(xml_file);
 
1351
    }
 
1352
  }
 
1353
  fputs(" />\n", xml_file);
 
1354
  check_io(xml_file);
 
1355
}
 
1356
 
 
1357
 
 
1358
/*
 
1359
  Print hex value for blob data.
 
1360
 
 
1361
  SYNOPSIS
 
1362
    print_blob_as_hex()
 
1363
    output_file         - output file
 
1364
    str                 - string to print
 
1365
    len                 - its length
 
1366
 
 
1367
  DESCRIPTION
 
1368
    Print hex value for blob data.
 
1369
*/
 
1370
 
 
1371
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
 
1372
{
 
1373
    /* sakaik got the idea to to provide blob's in hex notation. */
 
1374
    const char *ptr= str, *end= ptr + len;
 
1375
    for (; ptr < end ; ptr++)
 
1376
      fprintf(output_file, "%02X", *((unsigned char *)ptr));
 
1377
    check_io(output_file);
 
1378
}
 
1379
 
 
1380
/*
 
1381
  get_table_structure -- retrievs database structure, prints out corresponding
 
1382
  CREATE statement and fills out insert_pat if the table is the type we will
 
1383
  be dumping.
 
1384
 
 
1385
  ARGS
 
1386
    table       - table name
 
1387
    db          - db name
 
1388
    table_type  - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
 
1389
    ignore_flag - what we must particularly ignore - see IGNORE_ defines above
 
1390
    num_fields  - number of fields in the table
 
1391
 
 
1392
  RETURN
 
1393
    true if success, false if error
 
1394
*/
 
1395
 
 
1396
static bool get_table_structure(char *table, char *db, char *table_type,
 
1397
                                char *ignore_flag, uint64_t *num_fields)
 
1398
{
 
1399
  bool    init=0, delayed, write_data, complete_insert;
 
1400
  char       *result_table, *opt_quoted_table;
 
1401
  const char *insert_option;
 
1402
  char       name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE+3];
 
1403
  char       table_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+3];
 
1404
  char       table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3];
 
1405
  char       query_buff[QUERY_LENGTH];
 
1406
  FILE       *sql_file= md_result_file;
 
1407
  drizzle_result_st result;
 
1408
  drizzle_row_t  row;
 
1409
 
 
1410
  *ignore_flag= check_if_ignore_table(table, table_type);
 
1411
 
 
1412
  delayed= opt_delayed;
 
1413
  if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
 
1414
  {
 
1415
    delayed= 0;
 
1416
    verbose_msg(_("-- Warning: Unable to use delayed inserts for table '%s' "
 
1417
                "because it's of type %s\n"), table, table_type);
 
1418
  }
 
1419
 
 
1420
  complete_insert= 0;
 
1421
  if ((write_data= !(*ignore_flag & IGNORE_DATA)))
 
1422
  {
 
1423
    complete_insert= opt_complete_insert;
 
1424
    insert_pat.clear();
 
1425
  }
 
1426
 
 
1427
  insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
 
1428
                  delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
 
1429
 
 
1430
  verbose_msg(_("-- Retrieving table structure for table %s...\n"), table);
 
1431
 
 
1432
  result_table=     quote_name(table, table_buff, 1);
 
1433
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
1434
 
 
1435
  if (opt_order_by_primary)
 
1436
  {
 
1437
    free(order_by);
 
1438
    order_by= primary_key_fields(result_table);
 
1439
  }
 
1440
 
 
1441
  if (!opt_xml)
 
1442
  {
 
1443
    /* using SHOW CREATE statement */
 
1444
    if (!opt_no_create_info)
 
1445
    {
 
1446
      /* Make an sql-file, if path was given iow. option -T was given */
 
1447
      char buff[20+FN_REFLEN];
 
1448
      const drizzle_column_st *column;
 
1449
 
 
1450
      snprintf(buff, sizeof(buff), "show create table %s", result_table);
 
1451
 
 
1452
      if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
1453
        return false;
 
1454
 
 
1455
      if (path)
 
1456
      {
 
1457
        if (!(sql_file= open_sql_file_for_table(table)))
 
1458
        {
 
1459
          drizzle_result_free(&result);
 
1460
          return false;
 
1461
        }
 
1462
 
 
1463
        write_header(sql_file, db);
 
1464
      }
 
1465
      if (!opt_xml && opt_comments)
 
1466
      {
 
1467
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
1468
                result_table);
 
1469
        check_io(sql_file);
 
1470
      }
 
1471
      if (opt_drop)
 
1472
      {
 
1473
      /*
 
1474
        Even if the "table" is a view, we do a DROP TABLE here.
 
1475
       */
 
1476
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
 
1477
        check_io(sql_file);
 
1478
      }
 
1479
 
 
1480
      column= drizzle_column_index(&result, 0);
 
1481
 
 
1482
      row= drizzle_row_next(&result);
 
1483
 
 
1484
      fprintf(sql_file, "%s;\n", row[1]);
 
1485
 
 
1486
      check_io(sql_file);
 
1487
      drizzle_result_free(&result);
 
1488
    }
 
1489
 
 
1490
    snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
1491
             result_table);
 
1492
 
 
1493
    if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
 
1494
    {
 
1495
      if (path)
 
1496
        fclose(sql_file);
 
1497
      return false;
 
1498
    }
 
1499
 
 
1500
    /*
 
1501
      If write_data is true, then we build up insert statements for
 
1502
      the table's data. Note: in subsequent lines of code, this test
 
1503
      will have to be performed each time we are appending to
 
1504
      insert_pat.
 
1505
    */
 
1506
    if (write_data)
 
1507
    {
 
1508
      if (opt_replace_into)
 
1509
        insert_pat.append("REPLACE ");
 
1510
      else
 
1511
        insert_pat.append("INSERT ");
 
1512
      insert_pat.append(insert_option);
 
1513
      insert_pat.append("INTO ");
 
1514
      insert_pat.append(opt_quoted_table);
 
1515
      if (complete_insert)
 
1516
      {
 
1517
        insert_pat.append(" (");
 
1518
      }
 
1519
      else
 
1520
      {
 
1521
        insert_pat.append(" VALUES ");
 
1522
        if (!extended_insert)
 
1523
          insert_pat.append("(");
 
1524
      }
 
1525
    }
 
1526
 
 
1527
    while ((row= drizzle_row_next(&result)))
 
1528
    {
 
1529
      if (complete_insert)
 
1530
      {
 
1531
        if (init)
 
1532
        {
 
1533
          insert_pat.append(", ");
 
1534
        }
 
1535
        init=1;
 
1536
        insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
1537
      }
 
1538
    }
 
1539
    *num_fields= drizzle_result_row_count(&result);
 
1540
    drizzle_result_free(&result);
 
1541
  }
 
1542
  else
 
1543
  {
 
1544
    verbose_msg(_("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n"),
 
1545
                my_progname, drizzle_con_error(&dcon));
 
1546
 
 
1547
    snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
1548
             result_table);
 
1549
    if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
 
1550
      return false;
 
1551
 
 
1552
    /* Make an sql-file, if path was given iow. option -T was given */
 
1553
    if (!opt_no_create_info)
 
1554
    {
 
1555
      if (path)
 
1556
      {
 
1557
        if (!(sql_file= open_sql_file_for_table(table)))
 
1558
        {
 
1559
          drizzle_result_free(&result);
 
1560
          return false;
 
1561
        }
 
1562
        write_header(sql_file, db);
 
1563
      }
 
1564
      if (!opt_xml && opt_comments)
 
1565
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
1566
                result_table);
 
1567
      if (opt_drop)
 
1568
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
 
1569
      if (!opt_xml)
 
1570
        fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
 
1571
      else
 
1572
        print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
 
1573
                NULL);
 
1574
      check_io(sql_file);
 
1575
    }
 
1576
 
 
1577
    if (write_data)
 
1578
    {
 
1579
      if (opt_replace_into)
 
1580
        insert_pat.append("REPLACE ");
 
1581
      else
 
1582
        insert_pat.append("INSERT ");
 
1583
      insert_pat.append(insert_option);
 
1584
      insert_pat.append("INTO ");
 
1585
      insert_pat.append(result_table);
 
1586
      if (complete_insert)
 
1587
        insert_pat.append(" (");
 
1588
      else
 
1589
      {
 
1590
        insert_pat.append(" VALUES ");
 
1591
        if (!extended_insert)
 
1592
          insert_pat.append("(");
 
1593
      }
 
1594
    }
 
1595
 
 
1596
    while ((row= drizzle_row_next(&result)))
 
1597
    {
 
1598
      size_t *lengths= drizzle_row_field_sizes(&result);
 
1599
      if (init)
 
1600
      {
 
1601
        if (!opt_xml && !opt_no_create_info)
 
1602
        {
 
1603
          fputs(",\n",sql_file);
 
1604
          check_io(sql_file);
 
1605
        }
 
1606
        if (complete_insert)
 
1607
          insert_pat.append(", ");
 
1608
      }
 
1609
      init=1;
 
1610
      if (complete_insert)
 
1611
        insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
1612
      if (!opt_no_create_info)
 
1613
      {
 
1614
        if (opt_xml)
 
1615
        {
 
1616
          print_xml_row(sql_file, "field", &result, &row);
 
1617
          continue;
 
1618
        }
 
1619
 
 
1620
        if (opt_keywords)
 
1621
          fprintf(sql_file, "  %s.%s %s", result_table,
 
1622
                  quote_name(row[SHOW_FIELDNAME],name_buff, 0),
 
1623
                  row[SHOW_TYPE]);
 
1624
        else
 
1625
          fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
 
1626
                                                  name_buff, 0),
 
1627
                  row[SHOW_TYPE]);
 
1628
        if (row[SHOW_DEFAULT])
 
1629
        {
 
1630
          fputs(" DEFAULT ", sql_file);
 
1631
          unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
 
1632
        }
 
1633
        if (!row[SHOW_NULL][0])
 
1634
          fputs(" NOT NULL", sql_file);
 
1635
        if (row[SHOW_EXTRA][0])
 
1636
          fprintf(sql_file, " %s",row[SHOW_EXTRA]);
 
1637
        check_io(sql_file);
 
1638
      }
 
1639
    }
 
1640
    *num_fields= drizzle_result_row_count(&result);
 
1641
    drizzle_result_free(&result);
 
1642
 
 
1643
    if (!opt_no_create_info)
 
1644
    {
 
1645
      /* Make an sql-file, if path was given iow. option -T was given */
 
1646
      char buff[20+FN_REFLEN];
 
1647
      uint32_t keynr,primary_key;
 
1648
      snprintf(buff, sizeof(buff), "show keys from %s", result_table);
 
1649
      if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
1650
      {
 
1651
        fprintf(stderr, _("%s: Can't get keys for table %s\n"),
 
1652
                my_progname, result_table);
 
1653
        if (path)
 
1654
          fclose(sql_file);
 
1655
        return false;
 
1656
      }
 
1657
 
 
1658
      /* Find first which key is primary key */
 
1659
      keynr=0;
 
1660
      primary_key=INT_MAX;
 
1661
      while ((row= drizzle_row_next(&result)))
 
1662
      {
 
1663
        if (atoi(row[3]) == 1)
 
1664
        {
 
1665
          keynr++;
 
1666
#ifdef FORCE_PRIMARY_KEY
 
1667
          if (atoi(row[1]) == 0 && primary_key == INT_MAX)
 
1668
            primary_key=keynr;
 
1669
#endif
 
1670
          if (!strcmp(row[2],"PRIMARY"))
 
1671
          {
 
1672
            primary_key=keynr;
 
1673
            break;
 
1674
          }
 
1675
        }
 
1676
      }
 
1677
      drizzle_row_seek(&result,0);
 
1678
      keynr=0;
 
1679
      while ((row= drizzle_row_next(&result)))
 
1680
      {
 
1681
        if (opt_xml)
 
1682
        {
 
1683
          print_xml_row(sql_file, "key", &result, &row);
 
1684
          continue;
 
1685
        }
 
1686
 
 
1687
        if (atoi(row[3]) == 1)
 
1688
        {
 
1689
          if (keynr++)
 
1690
            putc(')', sql_file);
 
1691
          if (atoi(row[1]))       /* Test if duplicate key */
 
1692
            /* Duplicate allowed */
 
1693
            fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff,0));
 
1694
          else if (keynr == primary_key)
 
1695
            fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
 
1696
          else
 
1697
            fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff,
 
1698
                                                            0));
 
1699
        }
 
1700
        else
 
1701
          putc(',', sql_file);
 
1702
        fputs(quote_name(row[4], name_buff, 0), sql_file);
 
1703
        if (row[7])
 
1704
          fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
 
1705
        check_io(sql_file);
 
1706
      }
 
1707
      drizzle_result_free(&result);
 
1708
      if (!opt_xml)
 
1709
      {
 
1710
        if (keynr)
 
1711
          putc(')', sql_file);
 
1712
        fputs("\n)",sql_file);
 
1713
        check_io(sql_file);
 
1714
      }
 
1715
      /* Get DRIZZLE specific create options */
 
1716
      if (create_options)
 
1717
      {
 
1718
        char show_name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+2+24];
 
1719
 
 
1720
        /* Check memory for quote_for_like() */
 
1721
        snprintf(buff, sizeof(buff), "show table status like %s",
 
1722
                 quote_for_like(table, show_name_buff));
 
1723
 
 
1724
        if (!drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
1725
        {
 
1726
          if (!(row= drizzle_row_next(&result)))
 
1727
          {
 
1728
            fprintf(stderr,
 
1729
                    _("Error: Couldn't read status information for table %s\n"),
 
1730
                    result_table);
 
1731
          }
 
1732
          else
 
1733
          {
 
1734
            if (opt_xml)
 
1735
              print_xml_row(sql_file, "options", &result, &row);
 
1736
            else
 
1737
            {
 
1738
              fputs("/*!",sql_file);
 
1739
              print_value(sql_file,&result,row,"engine=","Engine",0);
 
1740
              print_value(sql_file,&result,row,"","Create_options",0);
 
1741
              print_value(sql_file,&result,row,"comment=","Comment",1);
 
1742
 
 
1743
              fputs(" */",sql_file);
 
1744
              check_io(sql_file);
 
1745
            }
 
1746
          }
 
1747
          drizzle_result_free(&result);
 
1748
        }
 
1749
      }
 
1750
      if (!opt_xml)
 
1751
        fputs(";\n", sql_file);
 
1752
      else
 
1753
        fputs("\t</table_structure>\n", sql_file);
 
1754
      check_io(sql_file);
 
1755
    }
 
1756
  }
 
1757
  if (complete_insert) {
 
1758
    insert_pat.append(") VALUES ");
 
1759
    if (!extended_insert)
 
1760
      insert_pat.append("(");
 
1761
  }
 
1762
  if (sql_file != md_result_file)
 
1763
  {
 
1764
    fputs("\n", sql_file);
 
1765
    write_footer(sql_file);
 
1766
    fclose(sql_file);
 
1767
  }
 
1768
  return true;
 
1769
} /* get_table_structure */
 
1770
 
 
1771
static void add_load_option(string &str, const char *option,
 
1772
                            const char *option_value)
 
1773
{
 
1774
  if (!option_value)
 
1775
  {
 
1776
    /* Null value means we don't add this option. */
 
1777
    return;
 
1778
  }
 
1779
 
 
1780
  str.append(option);
 
1781
 
 
1782
  if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
 
1783
  {
 
1784
    /* It's a hex constant, don't escape */
 
1785
    str.append(option_value);
 
1786
  }
 
1787
  else
 
1788
  {
 
1789
    /* char constant; escape */
 
1790
    field_escape(str, option_value);
 
1791
  }
 
1792
}
 
1793
 
 
1794
 
 
1795
/*
 
1796
  Allow the user to specify field terminator strings like:
 
1797
  "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
 
1798
  This is done by doubling ' and add a end -\ if needed to avoid
 
1799
  syntax errors from the SQL parser.
 
1800
*/
 
1801
 
 
1802
static void field_escape(string &in, const char *from)
 
1803
{
 
1804
  uint32_t end_backslashes= 0;
 
1805
 
 
1806
  in.append("'");
 
1807
 
 
1808
  while (*from)
 
1809
  {
 
1810
    in.append(from, 1);
 
1811
 
 
1812
    if (*from == '\\')
 
1813
      end_backslashes^=1;    /* find odd number of backslashes */
 
1814
    else
 
1815
    {
 
1816
      if (*from == '\'' && !end_backslashes)
 
1817
      {
 
1818
        /* We want a duplicate of "'" for DRIZZLE */
 
1819
        in.append("\'");
 
1820
      }
 
1821
      end_backslashes=0;
 
1822
    }
 
1823
    from++;
 
1824
  }
 
1825
  /* Add missing backslashes if user has specified odd number of backs.*/
 
1826
  if (end_backslashes)
 
1827
    in.append("\\");
 
1828
 
 
1829
  in.append("'");
 
1830
}
 
1831
 
 
1832
 
 
1833
 
 
1834
/*
 
1835
 
 
1836
 SYNOPSIS
 
1837
  dump_table()
 
1838
 
 
1839
  dump_table saves database contents as a series of INSERT statements.
 
1840
 
 
1841
  ARGS
 
1842
   table - table name
 
1843
   db    - db name
 
1844
 
 
1845
   RETURNS
 
1846
    void
 
1847
*/
 
1848
 
 
1849
 
 
1850
static void dump_table(char *table, char *db)
 
1851
{
 
1852
  char ignore_flag;
 
1853
  char table_buff[DRIZZLE_MAX_TABLE_SIZE+3];
 
1854
  string query_string;
 
1855
  char table_type[DRIZZLE_MAX_TABLE_SIZE];
 
1856
  char *result_table, table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3], *opt_quoted_table;
 
1857
  int error= 0;
 
1858
  uint32_t rownr, row_break, total_length, init_length;
 
1859
  uint64_t num_fields= 0;
 
1860
  drizzle_return_t ret;
 
1861
  drizzle_result_st result;
 
1862
  drizzle_column_st *column;
 
1863
  drizzle_row_t row;
 
1864
 
 
1865
 
 
1866
  /*
 
1867
    Make sure you get the create table info before the following check for
 
1868
    --no-data flag below. Otherwise, the create table info won't be printed.
 
1869
  */
 
1870
  if (!get_table_structure(table, db, table_type, &ignore_flag, &num_fields))
 
1871
  {
 
1872
    maybe_die(EX_TABLE_STATUS, _("Error retrieving table structure for table: \"%s\""), table);
 
1873
    return;
 
1874
  }
 
1875
 
 
1876
  /* Check --no-data flag */
 
1877
  if (opt_no_data)
 
1878
  {
 
1879
    verbose_msg(_("-- Skipping dump data for table '%s', --no-data was used\n"),
 
1880
                table);
 
1881
    return;
 
1882
  }
 
1883
 
 
1884
  /*
 
1885
    If the table type is a merge table or any type that has to be
 
1886
     _completely_ ignored and no data dumped
 
1887
  */
 
1888
  if (ignore_flag & IGNORE_DATA)
 
1889
  {
 
1890
    verbose_msg(_("-- Warning: Skipping data for table '%s' because " \
 
1891
                "it's of type %s\n"), table, table_type);
 
1892
    return;
 
1893
  }
 
1894
  /* Check that there are any fields in the table */
 
1895
  if (num_fields == 0)
 
1896
  {
 
1897
    verbose_msg(_("-- Skipping dump data for table '%s', it has no fields\n"),
 
1898
                table);
 
1899
    return;
 
1900
  }
 
1901
 
 
1902
  result_table= quote_name(table,table_buff, 1);
 
1903
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
1904
 
 
1905
  verbose_msg(_("-- Sending SELECT query...\n"));
 
1906
 
 
1907
  query_string.clear();
 
1908
  query_string.reserve(1024);
 
1909
 
 
1910
  if (path)
 
1911
  {
 
1912
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
1913
 
 
1914
    /*
 
1915
      Convert the path to native os format
 
1916
      and resolve to the full filepath.
 
1917
    */
 
1918
    convert_dirname(tmp_path,path,NULL);
 
1919
    my_load_path(tmp_path, tmp_path, NULL);
 
1920
    fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
 
1921
 
 
1922
    /* Must delete the file that 'INTO OUTFILE' will write to */
 
1923
    my_delete(filename, MYF(0));
 
1924
 
 
1925
    /* now build the query string */
 
1926
 
 
1927
    query_string.append( "SELECT * INTO OUTFILE '");
 
1928
    query_string.append( filename);
 
1929
    query_string.append( "'");
 
1930
 
 
1931
    if (fields_terminated || enclosed || opt_enclosed || escaped)
 
1932
      query_string.append( " FIELDS");
 
1933
 
 
1934
    add_load_option(query_string, " TERMINATED BY ", fields_terminated);
 
1935
    add_load_option(query_string, " ENCLOSED BY ", enclosed);
 
1936
    add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
 
1937
    add_load_option(query_string, " ESCAPED BY ", escaped);
 
1938
    add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
 
1939
 
 
1940
    query_string.append( " FROM ");
 
1941
    query_string.append( result_table);
 
1942
 
 
1943
    if (where)
 
1944
    {
 
1945
      query_string.append( " WHERE ");
 
1946
      query_string.append( where);
 
1947
    }
 
1948
 
 
1949
    if (order_by)
 
1950
    {
 
1951
      query_string.append( " ORDER BY ");
 
1952
      query_string.append( order_by);
 
1953
    }
 
1954
 
 
1955
    if (drizzle_query(&dcon, &result, query_string.c_str(),
 
1956
                      query_string.length(), &ret) == NULL ||
 
1957
        ret != DRIZZLE_RETURN_OK)
 
1958
    {
 
1959
      DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
 
1960
 
 
1961
      return;
 
1962
    }
 
1963
    drizzle_result_free(&result);
 
1964
  }
 
1965
  else
 
1966
  {
 
1967
    if (!opt_xml && opt_comments)
 
1968
    {
 
1969
      fprintf(md_result_file,_("\n--\n-- Dumping data for table %s\n--\n"),
 
1970
              result_table);
 
1971
      check_io(md_result_file);
 
1972
    }
 
1973
 
 
1974
    query_string.append( "SELECT * FROM ");
 
1975
    query_string.append( result_table);
 
1976
 
 
1977
    if (where)
 
1978
    {
 
1979
      if (!opt_xml && opt_comments)
 
1980
      {
 
1981
        fprintf(md_result_file, "-- WHERE:  %s\n", where);
 
1982
        check_io(md_result_file);
 
1983
      }
 
1984
 
 
1985
      query_string.append( " WHERE ");
 
1986
      query_string.append( where);
 
1987
    }
 
1988
    if (order_by)
 
1989
    {
 
1990
      if (!opt_xml && opt_comments)
 
1991
      {
 
1992
        fprintf(md_result_file, "-- ORDER BY:  %s\n", order_by);
 
1993
        check_io(md_result_file);
 
1994
      }
 
1995
      query_string.append( " ORDER BY ");
 
1996
      query_string.append( order_by);
 
1997
    }
 
1998
 
 
1999
    if (!opt_xml && !opt_compact)
 
2000
    {
 
2001
      fputs("\n", md_result_file);
 
2002
      check_io(md_result_file);
 
2003
    }
 
2004
    if (drizzleclient_query_with_error_report(&dcon, &result,
 
2005
                                              query_string.c_str(), quick))
 
2006
    {
 
2007
      goto err;
 
2008
    }
 
2009
 
 
2010
    verbose_msg(_("-- Retrieving rows...\n"));
 
2011
    if (drizzle_result_column_count(&result) != num_fields)
 
2012
    {
 
2013
      fprintf(stderr,_("%s: Error in field count for table: %s !  Aborting.\n"),
 
2014
              my_progname, result_table);
 
2015
      error= EX_CONSCHECK;
 
2016
      drizzle_result_free(&result);
 
2017
      goto err;
 
2018
    }
 
2019
 
 
2020
    if (opt_lock)
 
2021
    {
 
2022
      fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
 
2023
      check_io(md_result_file);
 
2024
    }
 
2025
    /* Moved disable keys to after lock per bug 15977 */
 
2026
    if (opt_disable_keys)
 
2027
    {
 
2028
      fprintf(md_result_file, "ALTER TABLE %s DISABLE KEYS;\n",
 
2029
              opt_quoted_table);
 
2030
      check_io(md_result_file);
 
2031
    }
 
2032
 
 
2033
    total_length= DRIZZLE_MAX_LINE_LENGTH;                /* Force row break */
 
2034
    row_break=0;
 
2035
    rownr=0;
 
2036
    init_length=(uint32_t) insert_pat.length()+4;
 
2037
    if (opt_xml)
 
2038
      print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
 
2039
              NULL);
 
2040
    if (opt_autocommit)
 
2041
    {
 
2042
      fprintf(md_result_file, "set autocommit=0;\n");
 
2043
      check_io(md_result_file);
 
2044
    }
 
2045
 
 
2046
    row= NULL;
 
2047
 
 
2048
    while (1)
 
2049
    {
 
2050
      uint32_t i;
 
2051
      size_t *lengths;
 
2052
 
 
2053
      if (quick)
 
2054
      {
 
2055
        if (row)
 
2056
          drizzle_row_free(&result, row);
 
2057
 
 
2058
        row= drizzle_row_buffer(&result, &ret);
 
2059
        if (ret != DRIZZLE_RETURN_OK)
 
2060
        {
 
2061
          fprintf(stderr,
 
2062
                _("%s: Error reading rows for table: %s (%d:%s) ! Aborting.\n"),
 
2063
                  my_progname, result_table, ret, drizzle_con_error(&dcon));
 
2064
          drizzle_result_free(&result);
 
2065
          goto err;
 
2066
        }
 
2067
      }
 
2068
      else
 
2069
        row= drizzle_row_next(&result);
 
2070
 
 
2071
      if (row == NULL)
 
2072
        break;
 
2073
 
 
2074
      lengths= drizzle_row_field_sizes(&result);
 
2075
 
 
2076
      rownr++;
 
2077
      if ((rownr % show_progress_size) == 0)
 
2078
      {
 
2079
        verbose_msg(_("-- %"PRIu32" of ~%"PRIu64" rows dumped for table %s\n"), rownr, total_rows, opt_quoted_table);
 
2080
      }
 
2081
      if (!extended_insert && !opt_xml)
 
2082
      {
 
2083
        fputs(insert_pat.c_str(),md_result_file);
 
2084
        check_io(md_result_file);
 
2085
      }
 
2086
      drizzle_column_seek(&result,0);
 
2087
 
 
2088
      if (opt_xml)
 
2089
      {
 
2090
        fputs("\t<row>\n", md_result_file);
 
2091
        check_io(md_result_file);
 
2092
      }
 
2093
 
 
2094
      for (i= 0; i < drizzle_result_column_count(&result); i++)
 
2095
      {
 
2096
        int is_blob;
 
2097
        uint32_t length= lengths[i];
 
2098
 
 
2099
        if (!(column= drizzle_column_next(&result)))
 
2100
          die(EX_CONSCHECK,
 
2101
                      _("Not enough fields from table %s! Aborting.\n"),
 
2102
                      result_table);
 
2103
 
 
2104
        /*
 
2105
           63 is my_charset_bin. If charsetnr is not 63,
 
2106
           we have not a BLOB but a TEXT column.
 
2107
           we'll dump in hex only BLOB columns.
 
2108
        */
 
2109
        is_blob= (opt_hex_blob && drizzle_column_charset(column) == 63 &&
 
2110
                  (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_VARCHAR ||
 
2111
                   drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_BLOB)) ? 1 : 0;
 
2112
        if (extended_insert && !opt_xml)
 
2113
        {
 
2114
          if (i == 0)
 
2115
          {
 
2116
            extended_row.clear();
 
2117
            extended_row.append("(");
 
2118
          }
 
2119
          else
 
2120
            extended_row.append(",");
 
2121
 
 
2122
          if (row[i])
 
2123
          {
 
2124
            if (length)
 
2125
            {
 
2126
              if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
 
2127
              {
 
2128
                /*
 
2129
                  "length * 2 + 2" is OK for both HEX and non-HEX modes:
 
2130
                  - In HEX mode we need exactly 2 bytes per character
 
2131
                  plus 2 bytes for '0x' prefix.
 
2132
                  - In non-HEX mode we need up to 2 bytes per character,
 
2133
                  plus 2 bytes for leading and trailing '\'' characters.
 
2134
                  Also we need to reserve 1 byte for terminating '\0'.
 
2135
                */
 
2136
                char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
 
2137
                memset(tmp_str, '\0', length * 2 + 2 + 1);
 
2138
                if (opt_hex_blob && is_blob)
 
2139
                {
 
2140
                  extended_row.append("0x");
 
2141
                  drizzle_hex_string(tmp_str, row[i], length);
 
2142
                  extended_row.append(tmp_str);
 
2143
                }
 
2144
                else
 
2145
                {
 
2146
                  extended_row.append("'");
 
2147
                  drizzle_escape_string(tmp_str, row[i],length);
 
2148
                  extended_row.append(tmp_str);
 
2149
                  extended_row.append("'");
 
2150
                }
 
2151
                free(tmp_str);
 
2152
              }
 
2153
              else
 
2154
              {
 
2155
                /* change any strings ("inf", "-inf", "nan") into NULL */
 
2156
                char *ptr= row[i];
 
2157
                if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
 
2158
                    my_isalpha(charset_info, ptr[1])))
 
2159
                  extended_row.append( "NULL");
 
2160
                else
 
2161
                {
 
2162
                  extended_row.append( ptr);
 
2163
                }
 
2164
              }
 
2165
            }
 
2166
            else
 
2167
              extended_row.append("''");
 
2168
          }
 
2169
          else
 
2170
            extended_row.append("NULL");
 
2171
        }
 
2172
        else
 
2173
        {
 
2174
          if (i && !opt_xml)
 
2175
          {
 
2176
            fputc(',', md_result_file);
 
2177
            check_io(md_result_file);
 
2178
          }
 
2179
          if (row[i])
 
2180
          {
 
2181
            if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
 
2182
            {
 
2183
              if (opt_xml)
 
2184
              {
 
2185
                if (opt_hex_blob && is_blob && length)
 
2186
                {
 
2187
                  /* Define xsi:type="xs:hexBinary" for hex encoded data */
 
2188
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2189
                                drizzle_column_name(column), "xsi:type=", "xs:hexBinary", NULL);
 
2190
                  print_blob_as_hex(md_result_file, row[i], length);
 
2191
                }
 
2192
                else
 
2193
                {
 
2194
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2195
                                drizzle_column_name(column), NULL);
 
2196
                  print_quoted_xml(md_result_file, row[i], length);
 
2197
                }
 
2198
                fputs("</field>\n", md_result_file);
 
2199
              }
 
2200
              else if (opt_hex_blob && is_blob && length)
 
2201
              {
 
2202
                fputs("0x", md_result_file);
 
2203
                print_blob_as_hex(md_result_file, row[i], length);
 
2204
              }
 
2205
              else
 
2206
                unescape(md_result_file, row[i], length);
 
2207
            }
 
2208
            else
 
2209
            {
 
2210
              /* change any strings ("inf", "-inf", "nan") into NULL */
 
2211
              char *ptr= row[i];
 
2212
              if (opt_xml)
 
2213
              {
 
2214
                print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2215
                        drizzle_column_name(column), NULL);
 
2216
                fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
 
2217
                      md_result_file);
 
2218
                fputs("</field>\n", md_result_file);
 
2219
              }
 
2220
              else if (my_isalpha(charset_info, *ptr) ||
 
2221
                       (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
 
2222
                fputs("NULL", md_result_file);
 
2223
              else
 
2224
                fputs(ptr, md_result_file);
 
2225
            }
 
2226
          }
 
2227
          else
 
2228
          {
 
2229
            /* The field value is NULL */
 
2230
            if (!opt_xml)
 
2231
              fputs("NULL", md_result_file);
 
2232
            else
 
2233
              print_xml_null_tag(md_result_file, "\t\t", "field name=",
 
2234
                                 drizzle_column_name(column), "\n");
 
2235
          }
 
2236
          check_io(md_result_file);
 
2237
        }
 
2238
      }
 
2239
 
 
2240
      if (opt_xml)
 
2241
      {
 
2242
        fputs("\t</row>\n", md_result_file);
 
2243
        check_io(md_result_file);
 
2244
      }
 
2245
 
 
2246
      if (extended_insert)
 
2247
      {
 
2248
        uint32_t row_length;
 
2249
        extended_row.append(")");
 
2250
        row_length= 2 + extended_row.length();
 
2251
        if (total_length + row_length < DRIZZLE_MAX_LINE_LENGTH)
 
2252
        {
 
2253
          total_length+= row_length;
 
2254
          fputc(',',md_result_file);            /* Always row break */
 
2255
          fputs(extended_row.c_str(),md_result_file);
 
2256
        }
 
2257
        else
 
2258
        {
 
2259
          if (row_break)
 
2260
            fputs(";\n", md_result_file);
 
2261
          row_break=1;                          /* This is first row */
 
2262
 
 
2263
          fputs(insert_pat.c_str(),md_result_file);
 
2264
          fputs(extended_row.c_str(),md_result_file);
 
2265
          total_length= row_length+init_length;
 
2266
        }
 
2267
        check_io(md_result_file);
 
2268
      }
 
2269
      else if (!opt_xml)
 
2270
      {
 
2271
        fputs(");\n", md_result_file);
 
2272
        check_io(md_result_file);
 
2273
      }
 
2274
    }
 
2275
 
 
2276
    /* XML - close table tag and supress regular output */
 
2277
    if (opt_xml)
 
2278
        fputs("\t</table_data>\n", md_result_file);
 
2279
    else if (extended_insert && row_break)
 
2280
      fputs(";\n", md_result_file);             /* If not empty table */
 
2281
    fflush(md_result_file);
 
2282
    check_io(md_result_file);
 
2283
 
 
2284
    /* Moved enable keys to before unlock per bug 15977 */
 
2285
    if (opt_disable_keys)
 
2286
    {
 
2287
      fprintf(md_result_file,"ALTER TABLE %s ENABLE KEYS;\n",
 
2288
              opt_quoted_table);
 
2289
      check_io(md_result_file);
 
2290
    }
 
2291
    if (opt_lock)
 
2292
    {
 
2293
      fputs("UNLOCK TABLES;\n", md_result_file);
 
2294
      check_io(md_result_file);
 
2295
    }
 
2296
    if (opt_autocommit)
 
2297
    {
 
2298
      fprintf(md_result_file, "commit;\n");
 
2299
      check_io(md_result_file);
 
2300
    }
 
2301
    drizzle_result_free(&result);
 
2302
  }
 
2303
  return;
 
2304
 
 
2305
err:
 
2306
  maybe_exit(error);
 
2307
  return;
 
2308
} /* dump_table */
 
2309
 
 
2310
 
 
2311
static char *getTableName(int reset)
 
2312
{
 
2313
  static drizzle_result_st result;
 
2314
  static bool have_result= false;
 
2315
  drizzle_row_t row;
 
2316
 
 
2317
  if (!have_result)
 
2318
  {
 
2319
    if (drizzleclient_query_with_error_report(&dcon, &result, "SHOW TABLES", false))
 
2320
      return NULL;
 
2321
    have_result= true;
 
2322
  }
 
2323
 
 
2324
  if ((row= drizzle_row_next(&result)))
 
2325
    return row[0];
 
2326
 
 
2327
  if (reset)
 
2328
    drizzle_row_seek(&result, 0);
 
2329
  else
 
2330
  {
 
2331
    drizzle_result_free(&result);
 
2332
    have_result= false;
 
2333
  }
 
2334
  return NULL;
 
2335
} /* getTableName */
 
2336
 
 
2337
 
365
2338
static int dump_all_databases()
366
2339
{
367
2340
  drizzle_row_t row;
368
 
  drizzle_result_st *tableres;
 
2341
  drizzle_result_st tableres;
369
2342
  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)))
 
2343
 
 
2344
  if (drizzleclient_query_with_error_report(&dcon, &tableres, "SHOW DATABASES", false))
 
2345
    return 1;
 
2346
  while ((row= drizzle_row_next(&tableres)))
384
2347
  {
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);
 
2348
    if (dump_all_tables_in_db(row[0]))
 
2349
      result=1;
393
2350
  }
394
 
  db_connection->freeResult(tableres);
 
2351
  drizzle_result_free(&tableres);
395
2352
  return result;
396
2353
}
397
2354
/* dump_all_databases */
398
2355
 
399
2356
 
400
 
static int dump_databases(const vector<string> &db_names)
 
2357
static int dump_databases(char **db_names)
401
2358
{
402
2359
  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)
 
2360
  char **db;
 
2361
 
 
2362
 
 
2363
  for (db= db_names ; *db ; db++)
407
2364
  {
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);
 
2365
    if (dump_all_tables_in_db(*db))
 
2366
      result=1;
414
2367
  }
415
2368
  return(result);
416
2369
} /* dump_databases */
417
2370
 
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
 
 
 
2371
 
 
2372
/*
 
2373
Table Specific database initalization.
 
2374
 
 
2375
SYNOPSIS
 
2376
  init_dumping_tables
 
2377
  qdatabase      quoted name of the database
 
2378
 
 
2379
RETURN VALUES
 
2380
  0        Success.
 
2381
  1        Failure.
 
2382
*/
 
2383
 
 
2384
int init_dumping_tables(char *qdatabase)
 
2385
{
 
2386
  if (!opt_create_db)
 
2387
  {
 
2388
    char qbuf[256];
 
2389
    drizzle_row_t row;
 
2390
    drizzle_result_st result;
 
2391
    drizzle_return_t ret;
 
2392
 
 
2393
    snprintf(qbuf, sizeof(qbuf),
 
2394
             "SHOW CREATE DATABASE IF NOT EXISTS %s",
 
2395
             qdatabase);
 
2396
 
 
2397
    if (drizzle_query_str(&dcon, &result, qbuf, &ret) == NULL ||
 
2398
        ret != DRIZZLE_RETURN_OK)
 
2399
    {
 
2400
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
2401
        drizzle_result_free(&result);
 
2402
 
 
2403
      /* Old server version, dump generic CREATE DATABASE */
 
2404
      if (opt_drop_database)
 
2405
        fprintf(md_result_file,
 
2406
                "\nDROP DATABASE IF EXISTS %s;\n",
 
2407
                qdatabase);
 
2408
      fprintf(md_result_file,
 
2409
              "\nCREATE DATABASE IF NOT EXISTS %s;\n",
 
2410
              qdatabase);
 
2411
    }
 
2412
    else
 
2413
    {
 
2414
      if (drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
 
2415
      {
 
2416
        if (opt_drop_database)
 
2417
          fprintf(md_result_file,
 
2418
                  "\nDROP DATABASE IF EXISTS %s;\n",
 
2419
                  qdatabase);
 
2420
        row = drizzle_row_next(&result);
 
2421
        if (row != NULL && row[1])
 
2422
        {
 
2423
          fprintf(md_result_file,"\n%s;\n",row[1]);
 
2424
        }
 
2425
      }
 
2426
      drizzle_result_free(&result);
 
2427
    }
 
2428
  }
 
2429
  return(0);
 
2430
} /* init_dumping_tables */
 
2431
 
 
2432
 
 
2433
static int init_dumping(char *database, int init_func(char*))
 
2434
{
 
2435
  drizzle_result_st result;
 
2436
  drizzle_return_t ret;
 
2437
 
 
2438
  if (!my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
 
2439
    return 1;
 
2440
 
 
2441
  if (drizzle_select_db(&dcon, &result, database, &ret) == NULL ||
 
2442
        ret != DRIZZLE_RETURN_OK)
 
2443
  {
 
2444
    DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
 
2445
    return 1;                   /* If --force */
 
2446
  }
 
2447
  drizzle_result_free(&result);
 
2448
 
 
2449
  if (!path && !opt_xml)
 
2450
  {
 
2451
    if (opt_databases || opt_alldbs)
 
2452
    {
 
2453
      /*
 
2454
        length of table name * 2 (if name contains quotes), 2 quotes and 0
 
2455
      */
 
2456
      char quoted_database_buf[DRIZZLE_MAX_DB_SIZE*2+3];
 
2457
      char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
 
2458
      if (opt_comments)
 
2459
      {
 
2460
        fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
 
2461
        check_io(md_result_file);
 
2462
      }
 
2463
 
 
2464
      /* Call the view or table specific function */
 
2465
      init_func(qdatabase);
 
2466
 
 
2467
      fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
 
2468
      check_io(md_result_file);
 
2469
    }
 
2470
  }
 
2471
  if (extended_insert)
 
2472
    extended_row.clear();
436
2473
  return 0;
 
2474
} /* init_dumping */
 
2475
 
 
2476
 
 
2477
/* Return 1 if we should copy the table */
 
2478
 
 
2479
static bool include_table(const unsigned char *hash_key, size_t len)
 
2480
{
 
2481
  return !hash_search(&ignore_table, hash_key, len);
 
2482
}
 
2483
 
 
2484
 
 
2485
static int dump_all_tables_in_db(char *database)
 
2486
{
 
2487
  char *table;
 
2488
  uint32_t numrows;
 
2489
  char table_buff[DRIZZLE_MAX_TABLE_SIZE*2+3];
 
2490
  char hash_key[DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2];  /* "db.tablename" */
 
2491
  char *afterdot;
 
2492
  drizzle_result_st result;
 
2493
  drizzle_return_t ret;
 
2494
 
 
2495
  afterdot= strcpy(hash_key, database) + strlen(database);
 
2496
  *afterdot++= '.';
 
2497
 
 
2498
  if (init_dumping(database, init_dumping_tables))
 
2499
    return(1);
 
2500
  if (opt_xml)
 
2501
    print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NULL);
 
2502
  if (lock_tables)
 
2503
  {
 
2504
    string query("LOCK TABLES ");
 
2505
    for (numrows= 0 ; (table= getTableName(1)) ; )
 
2506
    {
 
2507
      char *end= strcpy(afterdot, table) + strlen(table);
 
2508
      if (include_table((unsigned char*) hash_key,end - hash_key))
 
2509
      {
 
2510
        numrows++;
 
2511
        query.append( quote_name(table, table_buff, 1));
 
2512
        query.append( " READ LOCAL,");
 
2513
      }
 
2514
    }
 
2515
    if (numrows)
 
2516
    {
 
2517
      if (drizzle_query(&dcon, &result, query.c_str(),
 
2518
                        query.length()-1, &ret) == NULL ||
 
2519
          ret != DRIZZLE_RETURN_OK)
 
2520
      {
 
2521
        DB_error(&result, ret, _("when using LOCK TABLES"));
 
2522
        /* We shall continue here, if --force was given */
 
2523
      }
 
2524
      else
 
2525
        drizzle_result_free(&result);
 
2526
    }
 
2527
    query.clear();
 
2528
  }
 
2529
  if (flush_logs)
 
2530
  {
 
2531
    if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
 
2532
        ret != DRIZZLE_RETURN_OK)
 
2533
    {
 
2534
      DB_error(&result, ret, _("when doing refresh"));
 
2535
      /* We shall continue here, if --force was given */
 
2536
    }
 
2537
    else
 
2538
      drizzle_result_free(&result);
 
2539
  }
 
2540
  while ((table= getTableName(0)))
 
2541
  {
 
2542
    char *end= strcpy(afterdot, table) + strlen(table);
 
2543
    if (include_table((unsigned char*) hash_key, end - hash_key))
 
2544
    {
 
2545
      dump_table(table,database);
 
2546
      free(order_by);
 
2547
      order_by= 0;
 
2548
    }
 
2549
  }
 
2550
  if (opt_xml)
 
2551
  {
 
2552
    fputs("</database>\n", md_result_file);
 
2553
    check_io(md_result_file);
 
2554
  }
 
2555
  if (lock_tables)
 
2556
  {
 
2557
    if (!drizzleclient_query_with_error_report(&dcon, &result, "UNLOCK TABLES", false))
 
2558
      drizzle_result_free(&result);
 
2559
  }
 
2560
 
 
2561
  return(0);
 
2562
} /* dump_all_tables_in_db */
 
2563
 
 
2564
 
 
2565
/*
 
2566
  get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
 
2567
  table name from the server for the table name given on the command line.
 
2568
  we do this because the table name given on the command line may be a
 
2569
  different case (e.g.  T1 vs t1)
 
2570
 
 
2571
  RETURN
 
2572
    pointer to the table name
 
2573
    0 if error
 
2574
*/
 
2575
 
 
2576
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
 
2577
{
 
2578
  char *name= 0;
 
2579
  drizzle_result_st result;
 
2580
  drizzle_row_t  row;
 
2581
  char query[50 + 2*DRIZZLE_MAX_TABLE_SIZE];
 
2582
  char show_name_buff[FN_REFLEN];
 
2583
  uint64_t num_rows;
 
2584
 
 
2585
 
 
2586
  /* Check memory for quote_for_like() */
 
2587
  assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
 
2588
  snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
 
2589
           quote_for_like(old_table_name, show_name_buff));
 
2590
 
 
2591
  if (drizzleclient_query_with_error_report(&dcon, &result, query, false))
 
2592
    return NULL;
 
2593
 
 
2594
  num_rows= drizzle_result_row_count(&result);
 
2595
  if (num_rows > 0)
 
2596
  {
 
2597
    size_t *lengths;
 
2598
    /*
 
2599
      Return first row
 
2600
      TODO: Return all matching rows
 
2601
    */
 
2602
    row= drizzle_row_next(&result);
 
2603
    lengths= drizzle_row_field_sizes(&result);
 
2604
    name= strmake_root(root, row[0], lengths[0]);
 
2605
  }
 
2606
  drizzle_result_free(&result);
 
2607
 
 
2608
  return(name);
 
2609
}
 
2610
 
 
2611
 
 
2612
static int dump_selected_tables(char *db, char **table_names, int tables)
 
2613
{
 
2614
  char table_buff[DRIZZLE_MAX_TABLE_SIZE*2+3];
 
2615
  string lock_tables_query("LOCK TABLES ");
 
2616
  MEM_ROOT root;
 
2617
  char **dump_tables, **pos, **end;
 
2618
  drizzle_result_st result;
 
2619
  drizzle_return_t ret;
 
2620
 
 
2621
 
 
2622
  if (init_dumping(db, init_dumping_tables))
 
2623
    return(1);
 
2624
 
 
2625
  init_alloc_root(&root, 8192, 0);
 
2626
  if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
 
2627
     die(EX_EOM, _("alloc_root failure."));
 
2628
 
 
2629
  for (; tables > 0 ; tables-- , table_names++)
 
2630
  {
 
2631
    /* the table name passed on commandline may be wrong case */
 
2632
    if ((*pos= get_actual_table_name(*table_names, &root)))
 
2633
    {
 
2634
      /* Add found table name to lock_tables_query */
 
2635
      if (lock_tables)
 
2636
      {
 
2637
        lock_tables_query.append( quote_name(*pos, table_buff, 1));
 
2638
        lock_tables_query.append( " READ LOCAL,");
 
2639
      }
 
2640
      pos++;
 
2641
    }
 
2642
    else
 
2643
    {
 
2644
      if (!ignore_errors)
 
2645
      {
 
2646
        free_root(&root, MYF(0));
 
2647
      }
 
2648
      maybe_die(EX_ILLEGAL_TABLE, _("Couldn't find table: \"%s\""), *table_names);
 
2649
      /* We shall countinue here, if --force was given */
 
2650
    }
 
2651
  }
 
2652
  end= pos;
 
2653
 
 
2654
  if (lock_tables)
 
2655
  {
 
2656
    if (drizzle_query(&dcon, &result, lock_tables_query.c_str(),
 
2657
                      lock_tables_query.length()-1, &ret) == NULL ||
 
2658
        ret != DRIZZLE_RETURN_OK)
 
2659
    {
 
2660
      if (!ignore_errors)
 
2661
      {
 
2662
        free_root(&root, MYF(0));
 
2663
      }
 
2664
      DB_error(&result, ret, _("when doing LOCK TABLES"));
 
2665
      /* We shall countinue here, if --force was given */
 
2666
    }
 
2667
    else
 
2668
      drizzle_result_free(&result);
 
2669
  }
 
2670
  if (flush_logs)
 
2671
  {
 
2672
    if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
 
2673
        ret != DRIZZLE_RETURN_OK)
 
2674
    {
 
2675
      if (!ignore_errors)
 
2676
        free_root(&root, MYF(0));
 
2677
      DB_error(&result, ret, _("when doing refresh"));
 
2678
      /* We shall countinue here, if --force was given */
 
2679
    }
 
2680
    else
 
2681
      drizzle_result_free(&result);
 
2682
  }
 
2683
  if (opt_xml)
 
2684
    print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NULL);
 
2685
 
 
2686
  /* Dump each selected table */
 
2687
  for (pos= dump_tables; pos < end; pos++)
 
2688
    dump_table(*pos, db);
 
2689
 
 
2690
  free_root(&root, MYF(0));
 
2691
  free(order_by);
 
2692
  order_by= 0;
 
2693
  if (opt_xml)
 
2694
  {
 
2695
    fputs("</database>\n", md_result_file);
 
2696
    check_io(md_result_file);
 
2697
  }
 
2698
  if (lock_tables)
 
2699
  {
 
2700
    if (!(drizzleclient_query_with_error_report(&dcon, &result, "UNLOCK TABLES", false)))
 
2701
      drizzle_result_free(&result);
 
2702
  }
 
2703
  return(0);
437
2704
} /* dump_selected_tables */
438
2705
 
439
 
static int do_flush_tables_read_lock()
 
2706
 
 
2707
static int do_show_master_status(drizzle_con_st *drizzle_con)
 
2708
{
 
2709
  drizzle_row_t row;
 
2710
  drizzle_result_st master;
 
2711
  const char *comment_prefix=
 
2712
    (opt_master_data == DRIZZLE_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
 
2713
  if (drizzleclient_query_with_error_report(drizzle_con, &master, "SHOW MASTER STATUS", false))
 
2714
  {
 
2715
    return 1;
 
2716
  }
 
2717
  else
 
2718
  {
 
2719
    row= drizzle_row_next(&master);
 
2720
    if (row && row[0] && row[1])
 
2721
    {
 
2722
      /* SHOW MASTER STATUS reports file and position */
 
2723
      if (opt_comments)
 
2724
        fprintf(md_result_file,
 
2725
                "\n--\n-- Position to start replication or point-in-time "
 
2726
                "recovery from\n--\n\n");
 
2727
      fprintf(md_result_file,
 
2728
              "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
 
2729
              comment_prefix, row[0], row[1]);
 
2730
      check_io(md_result_file);
 
2731
    }
 
2732
    else if (!ignore_errors)
 
2733
    {
 
2734
      /* SHOW MASTER STATUS reports nothing and --force is not enabled */
 
2735
      my_printf_error(0, _("Error: Binlogging on server not active"),
 
2736
                      MYF(0));
 
2737
      drizzle_result_free(&master);
 
2738
      maybe_exit(EX_DRIZZLEERR);
 
2739
      return 1;
 
2740
    }
 
2741
    drizzle_result_free(&master);
 
2742
  }
 
2743
  return 0;
 
2744
}
 
2745
 
 
2746
static int do_stop_slave_sql(drizzle_con_st *drizzle_con)
 
2747
{
 
2748
  drizzle_result_st slave;
 
2749
  /* We need to check if the slave sql is running in the first place */
 
2750
  if (drizzleclient_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS", false))
 
2751
    return(1);
 
2752
  else
 
2753
  {
 
2754
    drizzle_row_t row= drizzle_row_next(&slave);
 
2755
    if (row && row[11])
 
2756
    {
 
2757
      /* if SLAVE SQL is not running, we don't stop it */
 
2758
      if (!strcmp(row[11],"No"))
 
2759
      {
 
2760
        drizzle_result_free(&slave);
 
2761
        /* Silently assume that they don't have the slave running */
 
2762
        return(0);
 
2763
      }
 
2764
    }
 
2765
  }
 
2766
  drizzle_result_free(&slave);
 
2767
 
 
2768
  /* now, stop slave if running */
 
2769
  if (drizzleclient_query_with_error_report(drizzle_con, &slave, "STOP SLAVE SQL_THREAD", false))
 
2770
    return(1);
 
2771
  drizzle_result_free(&slave);
 
2772
 
 
2773
  return(0);
 
2774
}
 
2775
 
 
2776
static int add_stop_slave(void)
 
2777
{
 
2778
  if (opt_comments)
 
2779
    fprintf(md_result_file,
 
2780
            "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
 
2781
  fprintf(md_result_file, "STOP SLAVE;\n");
 
2782
  return(0);
 
2783
}
 
2784
 
 
2785
static int add_slave_statements(void)
 
2786
{
 
2787
  if (opt_comments)
 
2788
    fprintf(md_result_file,
 
2789
            "\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
 
2790
  fprintf(md_result_file, "START SLAVE;\n");
 
2791
  return(0);
 
2792
}
 
2793
 
 
2794
static int do_show_slave_status(drizzle_con_st *drizzle_con)
 
2795
{
 
2796
  drizzle_result_st slave;
 
2797
  const char *comment_prefix=
 
2798
    (opt_slave_data == DRIZZLE_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
 
2799
  if (drizzleclient_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS", false))
 
2800
  {
 
2801
    if (!ignore_errors)
 
2802
    {
 
2803
      /* SHOW SLAVE STATUS reports nothing and --force is not enabled */
 
2804
      my_printf_error(0, _("Error: Slave not set up"), MYF(0));
 
2805
    }
 
2806
    return 1;
 
2807
  }
 
2808
  else
 
2809
  {
 
2810
    drizzle_row_t row= drizzle_row_next(&slave);
 
2811
    if (row && row[9] && row[21])
 
2812
    {
 
2813
      /* SHOW MASTER STATUS reports file and position */
 
2814
      if (opt_comments)
 
2815
        fprintf(md_result_file,
 
2816
                "\n--\n-- Position to start replication or point-in-time "
 
2817
                "recovery from (the master of this slave)\n--\n\n");
 
2818
 
 
2819
      fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
 
2820
 
 
2821
      if (opt_include_master_host_port)
 
2822
      {
 
2823
        if (row[1])
 
2824
          fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
 
2825
        if (row[3])
 
2826
          fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
 
2827
      }
 
2828
      fprintf(md_result_file,
 
2829
              "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
 
2830
 
 
2831
      check_io(md_result_file);
 
2832
    }
 
2833
    drizzle_result_free(&slave);
 
2834
  }
 
2835
  return 0;
 
2836
}
 
2837
 
 
2838
static int do_start_slave_sql(drizzle_con_st *drizzle_con)
 
2839
{
 
2840
  drizzle_result_st slave;
 
2841
  /* We need to check if the slave sql is stopped in the first place */
 
2842
  if (drizzleclient_query_with_error_report(drizzle_con, &slave, "SHOW SLAVE STATUS", false))
 
2843
    return(1);
 
2844
  else
 
2845
  {
 
2846
    drizzle_row_t row= drizzle_row_next(&slave);
 
2847
    if (row && row[11])
 
2848
    {
 
2849
      /* if SLAVE SQL is not running, we don't start it */
 
2850
      if (!strcmp(row[11],"Yes"))
 
2851
      {
 
2852
        drizzle_result_free(&slave);
 
2853
        /* Silently assume that they don't have the slave running */
 
2854
        return(0);
 
2855
      }
 
2856
    }
 
2857
    drizzle_result_free(&slave);
 
2858
  }
 
2859
 
 
2860
  /* now, start slave if stopped */
 
2861
  if (drizzleclient_query_with_error_report(drizzle_con, &slave, "START SLAVE", false))
 
2862
  {
 
2863
    my_printf_error(0, _("Error: Unable to start slave"), MYF(0));
 
2864
    return 1;
 
2865
  }
 
2866
  drizzle_result_free(&slave);
 
2867
  return(0);
 
2868
}
 
2869
 
 
2870
 
 
2871
 
 
2872
static int do_flush_tables_read_lock(drizzle_con_st *drizzle_con)
440
2873
{
441
2874
  /*
442
2875
    We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
443
2876
    will wait but will not stall the whole mysqld, and when the long update is
444
2877
    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
 
2878
    FLUSH TABLES is to lower the probability of a stage where both mysqldump
446
2879
    and most client connections are stalled. Of course, if a second long
447
2880
    update starts between the two FLUSHes, we have that bad stall.
448
2881
  */
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
 
}
 
2882
  return
 
2883
    ( drizzleclient_query_with_error_report(drizzle_con, 0, "FLUSH TABLES", false) ||
 
2884
      drizzleclient_query_with_error_report(drizzle_con, 0,
 
2885
                                    "FLUSH TABLES WITH READ LOCK", false) );
 
2886
}
 
2887
 
 
2888
 
 
2889
static int do_unlock_tables(drizzle_con_st *drizzle_con)
 
2890
{
 
2891
  return drizzleclient_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES", false);
 
2892
}
 
2893
 
 
2894
static int get_bin_log_name(drizzle_con_st *drizzle_con,
 
2895
                            char* buff_log_name, uint32_t buff_len)
 
2896
{
 
2897
  drizzle_result_st res;
 
2898
  drizzle_row_t row;
 
2899
 
 
2900
  if (drizzleclient_query_with_error_report(drizzle_con, &res, "SHOW MASTER STATUS", false))
 
2901
    return 1;
 
2902
 
 
2903
  if (!(row= drizzle_row_next(&res)))
 
2904
  {
 
2905
    drizzle_result_free(&res);
 
2906
    return 1;
 
2907
  }
 
2908
  /*
 
2909
    Only one row is returned, and the first column is the name of the
 
2910
    active log.
 
2911
  */
 
2912
  strncpy(buff_log_name, row[0], buff_len - 1);
 
2913
 
 
2914
  drizzle_result_free(&res);
 
2915
  return 0;
 
2916
}
 
2917
 
 
2918
static int purge_bin_logs_to(drizzle_con_st *drizzle_con, char* log_name)
 
2919
{
 
2920
  int err;
 
2921
  string str= "PURGE BINARY LOGS TO '";
 
2922
  str.append(log_name);
 
2923
  str.append("'");
 
2924
  drizzle_result_st res;
 
2925
  err= drizzleclient_query_with_error_report(drizzle_con, &res, str.c_str(),
 
2926
                                             false);
 
2927
  if (err)
 
2928
    return err;
 
2929
  drizzle_result_free(&res);
 
2930
  return 0;
 
2931
}
 
2932
 
 
2933
 
 
2934
static int start_transaction(drizzle_con_st *drizzle_con)
 
2935
{
 
2936
  return (drizzleclient_query_with_error_report(drizzle_con, 0,
 
2937
                                        "SET SESSION TRANSACTION ISOLATION "
 
2938
                                        "LEVEL REPEATABLE READ", false) ||
 
2939
          drizzleclient_query_with_error_report(drizzle_con, 0,
 
2940
                                        "START TRANSACTION "
 
2941
                                        "WITH CONSISTENT SNAPSHOT", false));
 
2942
}
 
2943
 
 
2944
 
 
2945
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
 
2946
                      char **err_pos, uint32_t *err_len)
 
2947
{
 
2948
  const char *end= x + length;
 
2949
  uint32_t found= 0;
 
2950
  uint32_t find;
 
2951
  char buff[255];
 
2952
 
 
2953
  *err_pos= 0;                  /* No error yet */
 
2954
  while (end > x && my_isspace(charset_info, end[-1]))
 
2955
    end--;
 
2956
 
 
2957
  *err_len= 0;
 
2958
  if (x != end)
 
2959
  {
 
2960
    const char *start= x;
 
2961
    for (;;)
 
2962
    {
 
2963
      const char *pos= start;
 
2964
      uint32_t var_len;
 
2965
 
 
2966
      for (; pos != end && *pos != ','; pos++) ;
 
2967
      var_len= (uint32_t) (pos - start);
 
2968
      strncpy(buff, start, min((uint32_t)sizeof(buff), var_len));
 
2969
      find= find_type(buff, lib, var_len);
 
2970
      if (!find)
 
2971
      {
 
2972
        *err_pos= (char*) start;
 
2973
        *err_len= var_len;
 
2974
      }
 
2975
      else
 
2976
        found|= (uint32_t)((int64_t) 1 << (find - 1));
 
2977
      if (pos == end)
 
2978
        break;
 
2979
      start= pos + 1;
 
2980
    }
 
2981
  }
 
2982
  return found;
 
2983
}
 
2984
 
 
2985
 
 
2986
/* Print a value with a prefix on file */
 
2987
static void print_value(FILE *file, drizzle_result_st  *result, drizzle_row_t row,
 
2988
                        const char *prefix, const char *name,
 
2989
                        int string_value)
 
2990
{
 
2991
  drizzle_column_st *column;
 
2992
  drizzle_column_seek(result, 0);
 
2993
 
 
2994
  for ( ; (column= drizzle_column_next(result)) ; row++)
 
2995
  {
 
2996
    if (!strcmp(drizzle_column_name(column),name))
 
2997
    {
 
2998
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
2999
      {
 
3000
        fputc(' ',file);
 
3001
        fputs(prefix, file);
 
3002
        if (string_value)
 
3003
          unescape(file,row[0],(uint32_t) strlen(row[0]));
 
3004
        else
 
3005
          fputs(row[0], file);
 
3006
        check_io(file);
 
3007
        return;
 
3008
      }
 
3009
    }
 
3010
  }
 
3011
  return;                                       /* This shouldn't happen */
 
3012
} /* print_value */
 
3013
 
 
3014
/**
 
3015
 * Fetches a row from a result based on a field name
 
3016
 * Returns const char* of the data in that row or NULL if not found
 
3017
 */
 
3018
 
 
3019
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row, const char *name)
 
3020
{
 
3021
  drizzle_column_st *column;
 
3022
  drizzle_column_seek(result, 0);
 
3023
 
 
3024
  for ( ; (column= drizzle_column_next(result)) ; row++)
 
3025
  {
 
3026
    if (!strcmp(drizzle_column_name(column),name))
 
3027
    {
 
3028
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
3029
      {
 
3030
        drizzle_column_seek(result, 0);
 
3031
        return row[0];
 
3032
      }
 
3033
    }
 
3034
  }
 
3035
  drizzle_column_seek(result, 0);
 
3036
  return NULL;
 
3037
}
 
3038
 
 
3039
 
 
3040
/*
 
3041
  SYNOPSIS
 
3042
 
 
3043
  Check if we the table is one of the table types that should be ignored:
 
3044
  MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
 
3045
  If the table should be altogether ignored, it returns a true, false if it
 
3046
  should not be ignored. If the user has selected to use INSERT DELAYED, it
 
3047
  sets the value of the bool pointer supports_delayed_inserts to 0 if not
 
3048
  supported, 1 if it is supported.
 
3049
 
 
3050
  ARGS
 
3051
 
 
3052
    check_if_ignore_table()
 
3053
    table_name                  Table name to check
 
3054
    table_type                  Type of table
 
3055
 
 
3056
  GLOBAL VARIABLES
 
3057
    drizzle                       Drizzle connection
 
3058
    verbose                     Write warning messages
 
3059
 
 
3060
  RETURN
 
3061
    char (bit value)            See IGNORE_ values at top
 
3062
*/
 
3063
 
 
3064
char check_if_ignore_table(const char *table_name, char *table_type)
 
3065
{
 
3066
  char result= IGNORE_NONE;
 
3067
  char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
 
3068
  const char *number_of_rows= NULL;
 
3069
  drizzle_result_st res;
 
3070
  drizzle_row_t row;
 
3071
 
 
3072
  /* Check memory for quote_for_like() */
 
3073
  assert(2*sizeof(table_name) < sizeof(show_name_buff));
 
3074
  snprintf(buff, sizeof(buff), "show table status like %s",
 
3075
           quote_for_like(table_name, show_name_buff));
 
3076
  if (drizzleclient_query_with_error_report(&dcon, &res, buff, false))
 
3077
  {
 
3078
    return result;
 
3079
  }
 
3080
  if (!(row= drizzle_row_next(&res)))
 
3081
  {
 
3082
    fprintf(stderr,
 
3083
            _("Error: Couldn't read status information for table %s\n"),
 
3084
            table_name);
 
3085
    drizzle_result_free(&res);
 
3086
    return(result);                         /* assume table is ok */
 
3087
  }
 
3088
  else
 
3089
  {
 
3090
    if ((number_of_rows= fetch_named_row(&res, row, "Rows")) != NULL)
 
3091
    {
 
3092
      total_rows= strtoul(number_of_rows, NULL, 10);
 
3093
    }
 
3094
  }
 
3095
  /*
 
3096
    If the table type matches any of these, we do support delayed inserts.
 
3097
    Note: we do not want to skip dumping this table if if is not one of
 
3098
    these types, but we do want to use delayed inserts in the dump if
 
3099
    the table type is _NOT_ one of these types
 
3100
    */
 
3101
  {
 
3102
    strncpy(table_type, row[1], DRIZZLE_MAX_TABLE_SIZE-1);
 
3103
    if (opt_delayed)
 
3104
    {
 
3105
      if (strcmp(table_type,"MyISAM") &&
 
3106
          strcmp(table_type,"ARCHIVE") &&
 
3107
          strcmp(table_type,"HEAP") &&
 
3108
          strcmp(table_type,"MEMORY"))
 
3109
        result= IGNORE_INSERT_DELAYED;
 
3110
    }
 
3111
  }
 
3112
  drizzle_result_free(&res);
 
3113
  return(result);
 
3114
}
 
3115
 
 
3116
 
 
3117
/*
 
3118
  Get string of comma-separated primary key field names
 
3119
 
 
3120
  SYNOPSIS
 
3121
    char *primary_key_fields(const char *table_name)
 
3122
    RETURNS     pointer to allocated buffer (must be freed by caller)
 
3123
    table_name  quoted table name
 
3124
 
 
3125
  DESCRIPTION
 
3126
    Use SHOW KEYS FROM table_name, allocate a buffer to hold the
 
3127
    field names, and then build that string and return the pointer
 
3128
    to that buffer.
 
3129
 
 
3130
    Returns NULL if there is no PRIMARY or UNIQUE key on the table,
 
3131
    or if there is some failure.  It is better to continue to dump
 
3132
    the table unsorted, rather than exit without dumping the data.
 
3133
*/
 
3134
 
 
3135
static char *primary_key_fields(const char *table_name)
 
3136
{
 
3137
  drizzle_result_st res;
 
3138
  drizzle_return_t ret;
 
3139
  drizzle_row_t  row;
 
3140
  /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
 
3141
  char show_keys_buff[15 + DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
 
3142
  uint32_t result_length= 0;
 
3143
  char *result= 0;
 
3144
  char buff[DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
 
3145
  char *quoted_field;
 
3146
 
 
3147
  snprintf(show_keys_buff, sizeof(show_keys_buff),
 
3148
           "SHOW KEYS FROM %s", table_name);
 
3149
  if (drizzle_query_str(&dcon, &res, show_keys_buff, &ret) == NULL ||
 
3150
      ret != DRIZZLE_RETURN_OK)
 
3151
  {
 
3152
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
3153
    {
 
3154
      fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
3155
              " records are NOT sorted (%s)\n"),
 
3156
              table_name, drizzle_result_error(&res));
 
3157
      drizzle_result_free(&res);
 
3158
    }
 
3159
    else
 
3160
    {
 
3161
      fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
3162
              " records are NOT sorted (%s)\n"),
 
3163
              table_name, drizzle_con_error(&dcon));
 
3164
    }
 
3165
 
 
3166
    return result;
 
3167
  }
 
3168
 
 
3169
  if (drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
3170
  {
 
3171
    fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
3172
            " records are NOT sorted (%s)\n"),
 
3173
            table_name, drizzle_con_error(&dcon));
 
3174
    return result;
 
3175
  }
 
3176
 
 
3177
  /*
 
3178
   * Figure out the length of the ORDER BY clause result.
 
3179
   * Note that SHOW KEYS is ordered:  a PRIMARY key is always the first
 
3180
   * row, and UNIQUE keys come before others.  So we only need to check
 
3181
   * the first key, not all keys.
 
3182
   */
 
3183
  if ((row= drizzle_row_next(&res)) && atoi(row[1]) == 0)
 
3184
  {
 
3185
    /* Key is unique */
 
3186
    do
 
3187
    {
 
3188
      quoted_field= quote_name(row[4], buff, 0);
 
3189
      result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
 
3190
    } while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1);
 
3191
  }
 
3192
 
 
3193
  /* Build the ORDER BY clause result */
 
3194
  if (result_length)
 
3195
  {
 
3196
    char *end;
 
3197
    /* result (terminating \0 is already in result_length) */
 
3198
    result= (char *)malloc(result_length + 10);
 
3199
    if (!result)
 
3200
    {
 
3201
      fprintf(stderr, _("Error: Not enough memory to store ORDER BY clause\n"));
 
3202
      drizzle_result_free(&res);
 
3203
      return result;
 
3204
    }
 
3205
    drizzle_row_seek(&res, 0);
 
3206
    row= drizzle_row_next(&res);
 
3207
    quoted_field= quote_name(row[4], buff, 0);
 
3208
    end= strcpy(result, quoted_field) + strlen(quoted_field);
 
3209
    while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1)
 
3210
    {
 
3211
      quoted_field= quote_name(row[4], buff, 0);
 
3212
      end+= sprintf(end,",%s",quoted_field);
 
3213
    }
 
3214
  }
 
3215
 
 
3216
  drizzle_result_free(&res);
 
3217
  return result;
 
3218
}
 
3219
 
468
3220
 
469
3221
int main(int argc, char **argv)
470
3222
{
471
 
try
472
 
{
 
3223
  char bin_log_name[FN_REFLEN];
473
3224
  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();
 
3225
  MY_INIT("drizzledump");
 
3226
  drizzle_result_st result;
 
3227
 
 
3228
  compatible_mode_normal_str[0]= 0;
 
3229
  default_charset= (char *)drizzle_universal_client_charset;
 
3230
  memset(&ignore_table, 0, sizeof(ignore_table));
 
3231
 
 
3232
  exit_code= get_options(&argc, &argv);
747
3233
  if (exit_code)
748
3234
  {
749
3235
    free_resources();
750
3236
    exit(exit_code);
751
3237
  }
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! */
 
3238
 
 
3239
  if (connect_to_db(current_host, current_user, opt_password))
 
3240
  {
 
3241
    free_resources();
 
3242
    exit(EX_DRIZZLEERR);
 
3243
  }
 
3244
  if (!path)
 
3245
    write_header(md_result_file, *argv);
 
3246
 
 
3247
  if (opt_slave_data && do_stop_slave_sql(&dcon))
 
3248
    goto err;
 
3249
 
 
3250
  if ((opt_lock_all_tables || opt_master_data) &&
 
3251
      do_flush_tables_read_lock(&dcon))
 
3252
    goto err;
 
3253
  if (opt_single_transaction && start_transaction(&dcon))
 
3254
      goto err;
 
3255
  if (opt_delete_master_logs)
 
3256
  {
 
3257
    if (drizzleclient_query_with_error_report(&dcon, &result, "FLUSH LOGS", false))
 
3258
      goto err;
 
3259
    drizzle_result_free(&result);
 
3260
    if (get_bin_log_name(&dcon, bin_log_name, sizeof(bin_log_name)))
 
3261
      goto err;
 
3262
    flush_logs= 0;
 
3263
  }
 
3264
  if (opt_lock_all_tables || opt_master_data)
 
3265
  {
 
3266
    if (drizzleclient_query_with_error_report(&dcon, &result, "FLUSH LOGS", false))
 
3267
      goto err;
 
3268
    drizzle_result_free(&result);
 
3269
    flush_logs= 0; /* not anymore; that would not be sensible */
 
3270
  }
 
3271
  /* Add 'STOP SLAVE to beginning of dump */
 
3272
  if (opt_slave_apply && add_stop_slave())
 
3273
    goto err;
 
3274
  if (opt_master_data && do_show_master_status(&dcon))
 
3275
    goto err;
 
3276
  if (opt_slave_data && do_show_slave_status(&dcon))
 
3277
    goto err;
 
3278
  if (opt_single_transaction && do_unlock_tables(&dcon)) /* unlock but no commit! */
790
3279
    goto err;
791
3280
 
792
3281
  if (opt_alldbs)
793
3282
  {
794
3283
    dump_all_databases();
795
 
    dump_all_tables();
796
3284
  }
797
 
  if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
 
3285
  else if (argc > 1 && !opt_databases)
798
3286
  {
799
 
    string database_used= *vm["database-used"].as< vector<string> >().begin();
800
3287
    /* 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();
 
3288
    dump_selected_tables(*argv, (argv + 1), (argc - 1));
 
3289
  }
828
3290
  else
829
 
    generate_dump_db();
 
3291
  {
 
3292
    dump_databases(argv);
 
3293
  }
 
3294
 
 
3295
  /* if --dump-slave , start the slave sql thread */
 
3296
  if (opt_slave_data && do_start_slave_sql(&dcon))
 
3297
    goto err;
 
3298
 
 
3299
  /* add 'START SLAVE' to end of dump */
 
3300
  if (opt_slave_apply && add_slave_statements())
 
3301
    goto err;
830
3302
 
831
3303
  /* ensure dumped data flushed */
832
3304
  if (md_result_file && fflush(md_result_file))
835
3307
      first_error= EX_DRIZZLEERR;
836
3308
    goto err;
837
3309
  }
 
3310
  /* everything successful, purge the old logs files */
 
3311
  if (opt_delete_master_logs && purge_bin_logs_to(&dcon, bin_log_name))
 
3312
    goto err;
838
3313
 
839
3314
  /*
840
3315
    No reason to explicitely COMMIT the transaction, neither to explicitely
843
3318
    server.
844
3319
  */
845
3320
err:
846
 
  delete db_connection;
847
 
  delete destination_connection;
848
 
  if (path.empty())
 
3321
  dbDisconnect(current_host);
 
3322
  if (!path)
849
3323
    write_footer(md_result_file);
850
3324
  free_resources();
851
3325
 
852
3326
  if (stderror_file)
853
3327
    fclose(stderror_file);
854
 
}
855
3328
 
856
 
  catch(exception &err)
857
 
  {
858
 
    cerr << err.what() << endl;
859
 
  }
860
 
  
861
3329
  return(first_error);
862
3330
} /* main */