~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

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