~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Monty Taylor
  • Date: 2008-10-16 06:32:59 UTC
  • mfrom: (518 drizzle)
  • mto: (511.1.5 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016063259-fwbqogq7lnezct0l
Merged with trunk.

Show diffs side-by-side

added added

removed removed

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