~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Monty Taylor
  • Date: 2008-11-07 00:15:51 UTC
  • mto: This revision was merged to the branch mainline in revision 579.
  • Revision ID: monty@inaugust.com-20081107001551-8vxb6sf1ti0i5p09
Cleaned up some headers for PCH.

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