~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to client/mysqldump.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000 MySQL AB
 
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 */
 
15
 
 
16
/* mysqldump.c  - Dump a tables contents and format to an ASCII file
 
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
 
25
** Adapted and optimized for MySQL by
 
26
** Michael Widenius, Sinisa Milivojevic, Jani Tolonen
 
27
** -w --where added 9/10/98 by Jim Faucette
 
28
** slave code by David Saez Padros <david@ols.es>
 
29
** master/autocommit code by Brian Aker <brian@tangent.org>
 
30
** SSL by
 
31
** Andrei Errapart <andreie@no.spam.ee>
 
32
** Tõnu Samuel  <tonu@please.do.not.remove.this.spam.ee>
 
33
** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up
 
34
** and adapted to mysqldump 05/11/01 by Jani Tolonen
 
35
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
 
36
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
 
37
*/
 
38
 
 
39
#define DUMP_VERSION "10.13"
 
40
 
 
41
#include <my_global.h>
 
42
#include <my_sys.h>
 
43
#include <my_user.h>
 
44
#include <m_string.h>
 
45
#include <m_ctype.h>
 
46
#include <hash.h>
 
47
#include <stdarg.h>
 
48
 
 
49
#include "client_priv.h"
 
50
#include "mysql.h"
 
51
#include "mysql_version.h"
 
52
#include "mysqld_error.h"
 
53
 
 
54
/* Exit codes */
 
55
 
 
56
#define EX_USAGE 1
 
57
#define EX_MYSQLERR 2
 
58
#define EX_CONSCHECK 3
 
59
#define EX_EOM 4
 
60
#define EX_EOF 5 /* ferror for output file was got */
 
61
#define EX_ILLEGAL_TABLE 6
 
62
 
 
63
/* index into 'show fields from table' */
 
64
 
 
65
#define SHOW_FIELDNAME  0
 
66
#define SHOW_TYPE  1
 
67
#define SHOW_NULL  2
 
68
#define SHOW_DEFAULT  4
 
69
#define SHOW_EXTRA  5
 
70
 
 
71
/* Size of buffer for dump's select query */
 
72
#define QUERY_LENGTH 1536
 
73
 
 
74
/* ignore table flags */
 
75
#define IGNORE_NONE 0x00 /* no ignore */
 
76
#define IGNORE_DATA 0x01 /* don't dump data for this table */
 
77
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
 
78
 
 
79
static void add_load_option(DYNAMIC_STRING *str, const char *option,
 
80
                             const char *option_value);
 
81
static ulong find_set(TYPELIB *lib, const char *x, uint length,
 
82
                      char **err_pos, uint *err_len);
 
83
static char *alloc_query_str(ulong size);
 
84
 
 
85
static void field_escape(DYNAMIC_STRING* in, const char *from);
 
86
static my_bool  verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
 
87
                quick= 1, extended_insert= 1,
 
88
                lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0,
 
89
                opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
 
90
                opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
 
91
                opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,
 
92
                opt_set_charset=0, opt_dump_date=1,
 
93
                opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
 
94
                opt_delete_master_logs=0, tty_password=0,
 
95
                opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
 
96
                opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
 
97
                opt_complete_insert= 0, opt_drop_database= 0,
 
98
                opt_replace_into= 0,
 
99
                opt_routines=0, opt_tz_utc=1,
 
100
                opt_slave_apply= 0, 
 
101
                opt_include_master_host_port= 0,
 
102
                opt_events= 0,
 
103
                opt_alltspcs=0, opt_notspcs= 0;
 
104
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
 
105
static ulong opt_max_allowed_packet, opt_net_buffer_length;
 
106
static MYSQL mysql_connection,*mysql=0;
 
107
static DYNAMIC_STRING insert_pat;
 
108
static char  *opt_password=0,*current_user=0,
 
109
             *current_host=0,*path=0,*fields_terminated=0,
 
110
             *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
 
111
             *where=0, *order_by=0,
 
112
             *opt_compatible_mode_str= 0,
 
113
             *err_ptr= 0,
 
114
             *log_error_file= NULL;
 
115
static char **defaults_argv= 0;
 
116
static char compatible_mode_normal_str[255];
 
117
/* Server supports character_set_results session variable? */
 
118
static my_bool server_supports_switching_charsets= TRUE;
 
119
static ulong opt_compatible_mode= 0;
 
120
#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
 
121
#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
 
122
#define MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL 1
 
123
#define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2
 
124
static uint opt_mysql_port= 0, opt_master_data;
 
125
static uint opt_slave_data;
 
126
static uint my_end_arg;
 
127
static char * opt_mysql_unix_port=0;
 
128
static int   first_error=0;
 
129
static DYNAMIC_STRING extended_row;
 
130
FILE *md_result_file= 0;
 
131
FILE *stderror_file=0;
 
132
 
 
133
#ifdef HAVE_SMEM
 
134
static char *shared_memory_base_name=0;
 
135
#endif
 
136
static uint opt_protocol= 0;
 
137
 
 
138
/*
 
139
Dynamic_string wrapper functions. In this file use these
 
140
wrappers, they will terminate the process if there is
 
141
an allocation failure.
 
142
*/
 
143
static void init_dynamic_string_checked(DYNAMIC_STRING *str, const char *init_str,
 
144
                            uint init_alloc, uint alloc_increment);
 
145
static void dynstr_append_checked(DYNAMIC_STRING* dest, const char* src);
 
146
static void dynstr_set_checked(DYNAMIC_STRING *str, const char *init_str);
 
147
static void dynstr_append_mem_checked(DYNAMIC_STRING *str, const char *append,
 
148
                          uint length);
 
149
static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size);
 
150
/*
 
151
  Constant for detection of default value of default_charset.
 
152
  If default_charset is equal to mysql_universal_client_charset, then
 
153
  it is the default value which assigned at the very beginning of main().
 
154
*/
 
155
static const char *mysql_universal_client_charset=
 
156
  MYSQL_UNIVERSAL_CLIENT_CHARSET;
 
157
static char *default_charset;
 
158
static CHARSET_INFO *charset_info= &my_charset_latin1;
 
159
const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace";
 
160
/* have we seen any VIEWs during table scanning? */
 
161
my_bool seen_views= 0;
 
162
const char *compatible_mode_names[]=
 
163
{
 
164
  "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
 
165
  "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
 
166
  "ANSI",
 
167
  NullS
 
168
};
 
169
#define MASK_ANSI_QUOTES \
 
170
(\
 
171
 (1<<2)  | /* POSTGRESQL */\
 
172
 (1<<3)  | /* ORACLE     */\
 
173
 (1<<4)  | /* MSSQL      */\
 
174
 (1<<5)  | /* DB2        */\
 
175
 (1<<6)  | /* MAXDB      */\
 
176
 (1<<10)   /* ANSI       */\
 
177
)
 
178
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
 
179
                                  "", compatible_mode_names, NULL};
 
180
 
 
181
HASH ignore_table;
 
182
 
 
183
static struct my_option my_long_options[] =
 
184
{
 
185
  {"all", 'a', "Deprecated. Use --create-options instead.",
 
186
   (uchar**) &create_options, (uchar**) &create_options, 0, GET_BOOL, NO_ARG, 1,
 
187
   0, 0, 0, 0, 0},
 
188
  {"all-databases", 'A',
 
189
   "Dump all the databases. This will be same as --databases with all databases selected.",
 
190
   (uchar**) &opt_alldbs, (uchar**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
191
   0, 0},
 
192
  {"all-tablespaces", 'Y',
 
193
   "Dump all the tablespaces.",
 
194
   (uchar**) &opt_alltspcs, (uchar**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
195
   0, 0},
 
196
  {"no-tablespaces", 'y',
 
197
   "Do not dump any tablespace information.",
 
198
   (uchar**) &opt_notspcs, (uchar**) &opt_notspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
199
   0, 0},
 
200
  {"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
 
201
   (uchar**) &opt_drop_database, (uchar**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
 
202
   0},
 
203
  {"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
 
204
   (uchar**) &opt_drop, (uchar**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
 
205
   0},
 
206
  {"add-locks", OPT_LOCKS, "Add locks around insert statements.",
 
207
   (uchar**) &opt_lock, (uchar**) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
 
208
   0},
 
209
  {"allow-keywords", OPT_KEYWORDS,
 
210
   "Allow creation of column names that are keywords.", (uchar**) &opt_keywords,
 
211
   (uchar**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
212
  {"apply-slave-statements", OPT_MYSQLDUMP_SLAVE_APPLY,
 
213
   "Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
 
214
   (uchar**) &opt_slave_apply, (uchar**) &opt_slave_apply, 0, GET_BOOL, NO_ARG,
 
215
   0, 0, 0, 0, 0, 0},
 
216
#ifdef __NETWARE__
 
217
  {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
 
218
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
219
#endif
 
220
  {"character-sets-dir", OPT_CHARSETS_DIR,
 
221
   "Directory where character sets are.", (uchar**) &charsets_dir,
 
222
   (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
223
  {"comments", 'i', "Write additional information.",
 
224
   (uchar**) &opt_comments, (uchar**) &opt_comments, 0, GET_BOOL, NO_ARG,
 
225
   1, 0, 0, 0, 0, 0},
 
226
  {"compatible", OPT_COMPATIBLE,
 
227
   "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 MySQL server version 4.1.0 or higher. This option is ignored with earlier server versions.",
 
228
   (uchar**) &opt_compatible_mode_str, (uchar**) &opt_compatible_mode_str, 0,
 
229
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
230
  {"compact", OPT_COMPACT,
 
231
   "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",
 
232
   (uchar**) &opt_compact, (uchar**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
233
   0, 0},
 
234
  {"complete-insert", 'c', "Use complete insert statements.",
 
235
   (uchar**) &opt_complete_insert, (uchar**) &opt_complete_insert, 0, GET_BOOL,
 
236
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
237
  {"compress", 'C', "Use compression in server/client protocol.",
 
238
   (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
239
   0, 0, 0},
 
240
  {"create-options", OPT_CREATE_OPTIONS,
 
241
   "Include all MySQL specific create options.",
 
242
   (uchar**) &create_options, (uchar**) &create_options, 0, GET_BOOL, NO_ARG, 1,
 
243
   0, 0, 0, 0, 0},
 
244
  {"databases", 'B',
 
245
   "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.",
 
246
   (uchar**) &opt_databases, (uchar**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
 
247
   0, 0, 0, 0},
 
248
#ifdef DBUG_OFF
 
249
  {"debug", '#', "This is a non-debug version. Catch this and exit",
 
250
   0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
251
#else
 
252
  {"debug", '#', "Output debug log", (uchar**) &default_dbug_option,
 
253
   (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
254
#endif
 
255
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
 
256
   (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
 
257
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
258
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
 
259
   (uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
 
260
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
261
  {"default-character-set", OPT_DEFAULT_CHARSET,
 
262
   "Set the default character set.", (uchar**) &default_charset,
 
263
   (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
264
  {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
 
265
   (uchar**) &opt_delayed, (uchar**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
266
   0, 0},
 
267
  {"delete-master-logs", OPT_DELETE_MASTER_LOGS,
 
268
   "Delete logs on master after backup. This automatically enables --master-data.",
 
269
   (uchar**) &opt_delete_master_logs, (uchar**) &opt_delete_master_logs, 0,
 
270
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
271
  {"disable-keys", 'K',
 
272
   "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (uchar**) &opt_disable_keys,
 
273
   (uchar**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
274
  {"dump-slave", OPT_MYSQLDUMP_SLAVE_DATA,
 
275
   "This causes the binary log position and filename of the master to be "
 
276
   "appended to the dumped data output. Setting the value to 1, will print"
 
277
   "it as a CHANGE MASTER command in the dumped data output; if equal"
 
278
   " to 2, that command will be prefixed with a comment symbol. "
 
279
   "This option will turn --lock-all-tables on, unless "
 
280
   "--single-transaction is specified too (in which case a "
 
281
   "global read lock is only taken a short time at the beginning of the dump "
 
282
   "- don't forget to read about --single-transaction below). In all cases "
 
283
   "any action on logs will happen at the exact moment of the dump."
 
284
   "Option automatically turns --lock-tables off.",
 
285
   (uchar**) &opt_slave_data, (uchar**) &opt_slave_data, 0,
 
286
   GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0},
 
287
  {"events", 'E', "Dump events.",
 
288
     (uchar**) &opt_events, (uchar**) &opt_events, 0, GET_BOOL,
 
289
     NO_ARG, 0, 0, 0, 0, 0, 0},
 
290
  {"extended-insert", 'e',
 
291
   "Allows utilization of the new, much faster INSERT syntax.",
 
292
   (uchar**) &extended_insert, (uchar**) &extended_insert, 0, GET_BOOL, NO_ARG,
 
293
   1, 0, 0, 0, 0, 0},
 
294
  {"fields-terminated-by", OPT_FTB,
 
295
   "Fields in the textfile are terminated by ...", (uchar**) &fields_terminated,
 
296
   (uchar**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
297
  {"fields-enclosed-by", OPT_ENC,
 
298
   "Fields in the importfile are enclosed by ...", (uchar**) &enclosed,
 
299
   (uchar**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
 
300
  {"fields-optionally-enclosed-by", OPT_O_ENC,
 
301
   "Fields in the i.file are opt. enclosed by ...", (uchar**) &opt_enclosed,
 
302
   (uchar**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
 
303
  {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
 
304
   (uchar**) &escaped, (uchar**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
305
  {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
 
306
   (uchar**) &opt_lock_all_tables, (uchar**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
 
307
   0, 0, 0, 0, 0, 0},
 
308
  {"flush-logs", 'F', "Flush logs file in server before starting dump. "
 
309
   "Note that if you dump many databases at once (using the option "
 
310
   "--databases= or --all-databases), the logs will be flushed for "
 
311
   "each database dumped. The exception is when using --lock-all-tables "
 
312
   "or --master-data: "
 
313
   "in this case the logs will be flushed only once, corresponding "
 
314
   "to the moment all tables are locked. So if you want your dump and "
 
315
   "the log flush to happen at the same exact moment you should use "
 
316
   "--lock-all-tables or --master-data with --flush-logs",
 
317
   (uchar**) &flush_logs, (uchar**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
318
   0, 0},
 
319
  {"flush-privileges", OPT_ESC, "Emit a FLUSH PRIVILEGES statement "
 
320
   "after dumping the mysql database.  This option should be used any "
 
321
   "time the dump contains the mysql database and any other database "
 
322
   "that depends on the data in the mysql database for proper restore. ",
 
323
   (uchar**) &flush_privileges, (uchar**) &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
324
   0, 0},
 
325
  {"force", 'f', "Continue even if we get an sql-error.",
 
326
   (uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG,
 
327
   0, 0, 0, 0, 0, 0},
 
328
  {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
 
329
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
330
  {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
 
331
    "VARBINARY, BLOB) in hexadecimal format.",
 
332
   (uchar**) &opt_hex_blob, (uchar**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
333
  {"host", 'h', "Connect to host.", (uchar**) &current_host,
 
334
   (uchar**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
335
  {"ignore-table", OPT_IGNORE_TABLE,
 
336
   "Do not dump the specified table. To specify more than one table to ignore, "
 
337
   "use the directive multiple times, once for each table.  Each table must "
 
338
   "be specified with both database and table names, e.g. --ignore-table=database.table",
 
339
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
340
  {"include-master-host-port", OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT,
 
341
   "Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' in dump produced with --dump-slave.",
 
342
   (uchar**) &opt_include_master_host_port, 
 
343
   (uchar**) &opt_include_master_host_port, 
 
344
   0, GET_BOOL, NO_ARG,
 
345
   0, 0, 0, 0, 0, 0},
 
346
  {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
 
347
   (uchar**) &opt_ignore, (uchar**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
348
   0, 0},
 
349
  {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
 
350
   (uchar**) &lines_terminated, (uchar**) &lines_terminated, 0, GET_STR,
 
351
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
352
  {"lock-all-tables", 'x', "Locks all tables across all databases. This "
 
353
   "is achieved by taking a global read lock for the duration of the whole "
 
354
   "dump. Automatically turns --single-transaction and --lock-tables off.",
 
355
   (uchar**) &opt_lock_all_tables, (uchar**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
 
356
   0, 0, 0, 0, 0, 0},
 
357
  {"lock-tables", 'l', "Lock all tables for read.", (uchar**) &lock_tables,
 
358
   (uchar**) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
359
  {"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.",
 
360
   (uchar**) &log_error_file, (uchar**) &log_error_file, 0, GET_STR,
 
361
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
362
  {"master-data", OPT_MASTER_DATA,
 
363
   "This causes the binary log position and filename to be appended to the "
 
364
   "output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
 
365
   " to 2, that command will be prefixed with a comment symbol. "
 
366
   "This option will turn --lock-all-tables on, unless "
 
367
   "--single-transaction is specified too (in which case a "
 
368
   "global read lock is only taken a short time at the beginning of the dump "
 
369
   "- don't forget to read about --single-transaction below). In all cases "
 
370
   "any action on logs will happen at the exact moment of the dump."
 
371
   "Option automatically turns --lock-tables off.",
 
372
   (uchar**) &opt_master_data, (uchar**) &opt_master_data, 0,
 
373
   GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
 
374
  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
 
375
    (uchar**) &opt_max_allowed_packet, (uchar**) &opt_max_allowed_packet, 0,
 
376
    GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
 
377
   (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
 
378
  {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
 
379
    (uchar**) &opt_net_buffer_length, (uchar**) &opt_net_buffer_length, 0,
 
380
    GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
 
381
   MALLOC_OVERHEAD-1024, 1024, 0},
 
382
  {"no-autocommit", OPT_AUTOCOMMIT,
 
383
   "Wrap tables with autocommit/commit statements.",
 
384
   (uchar**) &opt_autocommit, (uchar**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
 
385
   0, 0, 0, 0, 0, 0},
 
386
  {"no-create-db", 'n',
 
387
   "'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.}.",
 
388
   (uchar**) &opt_create_db, (uchar**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
 
389
   0, 0, 0, 0},
 
390
  {"no-create-info", 't', "Don't write table creation info.",
 
391
   (uchar**) &opt_no_create_info, (uchar**) &opt_no_create_info, 0, GET_BOOL,
 
392
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
393
  {"no-data", 'd', "No row information.", (uchar**) &opt_no_data,
 
394
   (uchar**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
395
  {"no-set-names", 'N',
 
396
   "Deprecated. Use --skip-set-charset instead.",
 
397
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
398
  {"opt", OPT_OPTIMIZE,
 
399
   "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.",
 
400
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
401
  {"order-by-primary", OPT_ORDER_BY_PRIMARY,
 
402
   "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.",
 
403
   (uchar**) &opt_order_by_primary, (uchar**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
404
  {"password", 'p',
 
405
   "Password to use when connecting to server. If password is not given it's solicited on the tty.",
 
406
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
407
#ifdef __WIN__
 
408
  {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
 
409
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
410
#endif
 
411
  {"port", 'P', "Port number to use for connection.", (uchar**) &opt_mysql_port,
 
412
   (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
 
413
   0},
 
414
  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
 
415
   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
416
  {"quick", 'q', "Don't buffer query, dump directly to stdout.",
 
417
   (uchar**) &quick, (uchar**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
418
  {"quote-names",'Q', "Quote table and column names with backticks (`).",
 
419
   (uchar**) &opt_quoted, (uchar**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
 
420
   0, 0},
 
421
  {"replace", OPT_MYSQL_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
 
422
   (uchar**) &opt_replace_into, (uchar**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
423
   0, 0},
 
424
  {"result-file", 'r',
 
425
   "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).",
 
426
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
427
  {"routines", 'R', "Dump stored routines (functions and procedures).",
 
428
     (uchar**) &opt_routines, (uchar**) &opt_routines, 0, GET_BOOL,
 
429
     NO_ARG, 0, 0, 0, 0, 0, 0},
 
430
  {"set-charset", OPT_SET_CHARSET,
 
431
   "Add 'SET NAMES default_character_set' to the output.",
 
432
   (uchar**) &opt_set_charset, (uchar**) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
 
433
   0, 0, 0, 0, 0},
 
434
  {"set-variable", 'O',
 
435
   "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
 
436
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
437
#ifdef HAVE_SMEM
 
438
  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
 
439
   "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
 
440
   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
441
#endif
 
442
  /*
 
443
    Note that the combination --single-transaction --master-data
 
444
    will give bullet-proof binlog position only if server >=4.1.3. That's the
 
445
    old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug.
 
446
  */
 
447
  {"single-transaction", OPT_TRANSACTION,
 
448
   "Creates a consistent snapshot by dumping all tables in a single "
 
449
   "transaction. Works ONLY for tables stored in storage engines which "
 
450
   "support multiversioning (currently only InnoDB does); the dump is NOT "
 
451
   "guaranteed to be consistent for other storage engines. "
 
452
   "While a --single-transaction dump is in process, to ensure a valid "
 
453
   "dump file (correct table contents and binary log position), no other "
 
454
   "connection should use the following statements: ALTER TABLE, DROP "
 
455
   "TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
 
456
   "isolated from them. Option automatically turns off --lock-tables.",
 
457
   (uchar**) &opt_single_transaction, (uchar**) &opt_single_transaction, 0,
 
458
   GET_BOOL, NO_ARG,  0, 0, 0, 0, 0, 0},
 
459
  {"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
 
460
   (uchar**) &opt_dump_date, (uchar**) &opt_dump_date, 0,
 
461
   GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
462
  {"skip-opt", OPT_SKIP_OPTIMIZATION,
 
463
   "Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
 
464
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
465
  {"socket", 'S', "Socket file to use for connection.",
 
466
   (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
 
467
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
468
  {"tab",'T',
 
469
   "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.",
 
470
   (uchar**) &path, (uchar**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
471
  {"tables", OPT_TABLES, "Overrides option --databases (-B).",
 
472
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
473
  {"tz-utc", OPT_TZ_UTC,
 
474
    "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.",
 
475
    (uchar**) &opt_tz_utc, (uchar**) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
476
#ifndef DONT_ALLOW_USER_CHANGE
 
477
  {"user", 'u', "User for login if not current user.",
 
478
   (uchar**) &current_user, (uchar**) &current_user, 0, GET_STR, REQUIRED_ARG,
 
479
   0, 0, 0, 0, 0, 0},
 
480
#endif
 
481
  {"verbose", 'v', "Print info about the various stages.",
 
482
   (uchar**) &verbose, (uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
483
  {"version",'V', "Output version information and exit.", 0, 0, 0,
 
484
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
485
  {"where", 'w', "Dump only selected records; QUOTES mandatory!",
 
486
   (uchar**) &where, (uchar**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
487
  {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
 
488
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
489
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
490
};
 
491
 
 
492
static const char *load_default_groups[]= { "mysqldump","client",0 };
 
493
 
 
494
static void maybe_exit(int error);
 
495
static void die(int error, const char* reason, ...);
 
496
static void maybe_die(int error, const char* reason, ...);
 
497
static void write_header(FILE *sql_file, char *db_name);
 
498
static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
 
499
                        const char *prefix,const char *name,
 
500
                        int string_value);
 
501
static int dump_selected_tables(char *db, char **table_names, int tables);
 
502
static int dump_all_tables_in_db(char *db);
 
503
static int init_dumping_views(char *);
 
504
static int init_dumping_tables(char *);
 
505
static int init_dumping(char *, int init_func(char*));
 
506
static int dump_databases(char **);
 
507
static int dump_all_databases();
 
508
static char *quote_name(const char *name, char *buff, my_bool force);
 
509
char check_if_ignore_table(const char *table_name, char *table_type);
 
510
static char *primary_key_fields(const char *table_name);
 
511
static my_bool get_view_structure(char *table, char* db);
 
512
static my_bool dump_all_views_in_db(char *database);
 
513
static int dump_all_tablespaces();
 
514
static int dump_tablespaces_for_tables(char *db, char **table_names, int tables);
 
515
static int dump_tablespaces_for_databases(char** databases);
 
516
static int dump_tablespaces(char* ts_where);
 
517
 
 
518
#include <help_start.h>
 
519
 
 
520
/*
 
521
  Print the supplied message if in verbose mode
 
522
 
 
523
  SYNOPSIS
 
524
    verbose_msg()
 
525
    fmt   format specifier
 
526
    ...   variable number of parameters
 
527
*/
 
528
 
 
529
static void verbose_msg(const char *fmt, ...)
 
530
{
 
531
  va_list args;
 
532
  DBUG_ENTER("verbose_msg");
 
533
 
 
534
  if (!verbose)
 
535
    DBUG_VOID_RETURN;
 
536
 
 
537
  va_start(args, fmt);
 
538
  vfprintf(stderr, fmt, args);
 
539
  va_end(args);
 
540
 
 
541
  DBUG_VOID_RETURN;
 
542
}
 
543
 
 
544
/*
 
545
  exit with message if ferror(file)
 
546
 
 
547
  SYNOPSIS
 
548
    check_io()
 
549
    file        - checked file
 
550
*/
 
551
 
 
552
void check_io(FILE *file)
 
553
{
 
554
  if (ferror(file))
 
555
    die(EX_EOF, "Got errno %d on write", errno);
 
556
}
 
557
 
 
558
static void print_version(void)
 
559
{
 
560
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
 
561
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
 
562
  NETWARE_SET_SCREEN_MODE(1);
 
563
} /* print_version */
 
564
 
 
565
 
 
566
static void short_usage_sub(void)
 
567
{
 
568
  printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
 
569
  printf("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
 
570
         my_progname);
 
571
  printf("OR     %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
 
572
  NETWARE_SET_SCREEN_MODE(1);
 
573
}
 
574
 
 
575
 
 
576
static void usage(void)
 
577
{
 
578
  print_version();
 
579
  puts("By Igor Romanenko, Monty, Jani & Sinisa");
 
580
  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");
 
581
  puts("Dumping definition and data mysql database or table");
 
582
  short_usage_sub();
 
583
  print_defaults("my",load_default_groups);
 
584
  my_print_help(my_long_options);
 
585
  my_print_variables(my_long_options);
 
586
} /* usage */
 
587
 
 
588
 
 
589
static void short_usage(void)
 
590
{
 
591
  short_usage_sub();
 
592
  printf("For more options, use %s --help\n", my_progname);
 
593
}
 
594
 
 
595
#include <help_end.h>
 
596
 
 
597
 
 
598
static void write_header(FILE *sql_file, char *db_name)
 
599
{
 
600
  if (opt_xml)
 
601
  {
 
602
    fputs("<?xml version=\"1.0\"?>\n", sql_file);
 
603
    /*
 
604
      Schema reference.  Allows use of xsi:nil for NULL values and 
 
605
      xsi:type to define an element's data type.
 
606
    */
 
607
    fputs("<mysqldump ", sql_file);
 
608
    fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
 
609
          sql_file);
 
610
    fputs(">\n", sql_file);
 
611
    check_io(sql_file);
 
612
  }
 
613
  else if (!opt_compact)
 
614
  {
 
615
    if (opt_comments)
 
616
    {
 
617
      fprintf(sql_file,
 
618
              "-- MySQL dump %s  Distrib %s, for %s (%s)\n--\n",
 
619
              DUMP_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
 
620
      fprintf(sql_file, "-- Host: %s    Database: %s\n",
 
621
              current_host ? current_host : "localhost", db_name ? db_name :
 
622
              "");
 
623
      fputs("-- ------------------------------------------------------\n",
 
624
            sql_file);
 
625
      fprintf(sql_file, "-- Server version\t%s\n",
 
626
              mysql_get_server_info(&mysql_connection));
 
627
    }
 
628
    if (opt_set_charset)
 
629
      fprintf(sql_file,
 
630
"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
 
631
"\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
 
632
"\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
 
633
"\n/*!40101 SET NAMES %s */;\n",default_charset);
 
634
 
 
635
    if (opt_tz_utc)
 
636
    {
 
637
      fprintf(sql_file, "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n");
 
638
      fprintf(sql_file, "/*!40103 SET TIME_ZONE='+00:00' */;\n");
 
639
    }
 
640
 
 
641
    if (!path)
 
642
    {
 
643
      fprintf(md_result_file,"\
 
644
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n\
 
645
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n\
 
646
");
 
647
    }
 
648
    check_io(sql_file);
 
649
  }
 
650
} /* write_header */
 
651
 
 
652
 
 
653
static void write_footer(FILE *sql_file)
 
654
{
 
655
  if (opt_xml)
 
656
  {
 
657
    fputs("</mysqldump>\n", sql_file);
 
658
    check_io(sql_file);
 
659
  }
 
660
  else if (!opt_compact)
 
661
  {
 
662
    if (opt_tz_utc)
 
663
      fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n");
 
664
 
 
665
    if (!path)
 
666
    {
 
667
      fprintf(md_result_file,"\
 
668
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
 
669
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
 
670
    }
 
671
    if (opt_set_charset)
 
672
      fprintf(sql_file,
 
673
"/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
 
674
"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
 
675
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
 
676
    fprintf(sql_file,
 
677
            "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
 
678
    fputs("\n", sql_file);
 
679
    if (opt_comments)
 
680
    {
 
681
      if (opt_dump_date)
 
682
      {
 
683
        char time_str[20];
 
684
        get_date(time_str, GETDATE_DATE_TIME, 0);
 
685
        fprintf(sql_file, "-- Dump completed on %s\n",
 
686
                time_str);
 
687
      }
 
688
      else
 
689
        fprintf(sql_file, "-- Dump completed\n");
 
690
    }
 
691
    check_io(sql_file);
 
692
  }
 
693
} /* write_footer */
 
694
 
 
695
 
 
696
static void free_table_ent(char *key)
 
697
{
 
698
  my_free(key, MYF(0));
 
699
}
 
700
 
 
701
 
 
702
uchar* get_table_key(const char *entry, size_t *length,
 
703
                     my_bool not_used __attribute__((unused)))
 
704
{
 
705
  *length= strlen(entry);
 
706
  return (uchar*) entry;
 
707
}
 
708
 
 
709
 
 
710
static my_bool
 
711
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
 
712
               char *argument)
 
713
{
 
714
  switch (optid) {
 
715
#ifdef __NETWARE__
 
716
  case OPT_AUTO_CLOSE:
 
717
    setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
 
718
    break;
 
719
#endif
 
720
  case 'p':
 
721
    if (argument)
 
722
    {
 
723
      char *start=argument;
 
724
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
 
725
      opt_password=my_strdup(argument,MYF(MY_FAE));
 
726
      while (*argument) *argument++= 'x';               /* Destroy argument */
 
727
      if (*start)
 
728
        start[1]=0;                             /* Cut length of argument */
 
729
      tty_password= 0;
 
730
    }
 
731
    else
 
732
      tty_password=1;
 
733
    break;
 
734
  case 'r':
 
735
    if (!(md_result_file= my_fopen(argument, O_WRONLY | FILE_BINARY,
 
736
                                    MYF(MY_WME))))
 
737
      exit(1);
 
738
    break;
 
739
  case 'W':
 
740
#ifdef __WIN__
 
741
    opt_protocol= MYSQL_PROTOCOL_PIPE;
 
742
#endif
 
743
    break;
 
744
  case 'N':
 
745
    opt_set_charset= 0;
 
746
    break;
 
747
  case 'T':
 
748
    opt_disable_keys=0;
 
749
 
 
750
    if (strlen(argument) >= FN_REFLEN)
 
751
    {
 
752
      /*
 
753
        This check is made because the some the file functions below
 
754
        have FN_REFLEN sized stack allocated buffers and will cause
 
755
        a crash even if the input destination buffer is large enough
 
756
        to hold the output.
 
757
      */
 
758
      die(EX_USAGE, "Input filename too long: %s", argument);
 
759
    }
 
760
 
 
761
    break;
 
762
  case '#':
 
763
    DBUG_PUSH(argument ? argument : default_dbug_option);
 
764
    debug_check_flag= 1;
 
765
    break;
 
766
  case 'V': print_version(); exit(0);
 
767
  case 'X':
 
768
    opt_xml= 1;
 
769
    extended_insert= opt_drop= opt_lock=
 
770
      opt_disable_keys= opt_autocommit= opt_create_db= 0;
 
771
    break;
 
772
  case 'I':
 
773
  case '?':
 
774
    usage();
 
775
    exit(0);
 
776
  case (int) OPT_MASTER_DATA:
 
777
    if (!argument) /* work like in old versions */
 
778
      opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
 
779
    break;
 
780
  case (int) OPT_MYSQLDUMP_SLAVE_DATA:
 
781
    if (!argument) /* work like in old versions */
 
782
      opt_slave_data= MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL;
 
783
    break;
 
784
  case (int) OPT_OPTIMIZE:
 
785
    extended_insert= opt_drop= opt_lock= quick= create_options=
 
786
      opt_disable_keys= lock_tables= opt_set_charset= 1;
 
787
    break;
 
788
  case (int) OPT_SKIP_OPTIMIZATION:
 
789
    extended_insert= opt_drop= opt_lock= quick= create_options=
 
790
      opt_disable_keys= lock_tables= opt_set_charset= 0;
 
791
    break;
 
792
  case (int) OPT_COMPACT:
 
793
  if (opt_compact)
 
794
  {
 
795
    opt_comments= opt_drop= opt_disable_keys= opt_lock= 0;
 
796
    opt_set_charset= 0;
 
797
  }
 
798
  case (int) OPT_TABLES:
 
799
    opt_databases=0;
 
800
    break;
 
801
  case (int) OPT_IGNORE_TABLE:
 
802
  {
 
803
    if (!strchr(argument, '.'))
 
804
    {
 
805
      fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n");
 
806
      exit(1);
 
807
    }
 
808
    if (my_hash_insert(&ignore_table, (uchar*)my_strdup(argument, MYF(0))))
 
809
      exit(EX_EOM);
 
810
    break;
 
811
  }
 
812
  case (int) OPT_COMPATIBLE:
 
813
    {
 
814
      char buff[255];
 
815
      char *end= compatible_mode_normal_str;
 
816
      int i;
 
817
      ulong mode;
 
818
      uint err_len;
 
819
 
 
820
      opt_quoted= 1;
 
821
      opt_set_charset= 0;
 
822
      opt_compatible_mode_str= argument;
 
823
      opt_compatible_mode= find_set(&compatible_mode_typelib,
 
824
                                    argument, strlen(argument),
 
825
                                    &err_ptr, &err_len);
 
826
      if (err_len)
 
827
      {
 
828
        strmake(buff, err_ptr, min(sizeof(buff), err_len));
 
829
        fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
 
830
        exit(1);
 
831
      }
 
832
#if !defined(DBUG_OFF)
 
833
      {
 
834
        uint size_for_sql_mode= 0;
 
835
        const char **ptr;
 
836
        for (ptr= compatible_mode_names; *ptr; ptr++)
 
837
          size_for_sql_mode+= strlen(*ptr);
 
838
        size_for_sql_mode+= sizeof(compatible_mode_names)-1;
 
839
        DBUG_ASSERT(sizeof(compatible_mode_normal_str)>=size_for_sql_mode);
 
840
      }
 
841
#endif
 
842
      mode= opt_compatible_mode;
 
843
      for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++)
 
844
      {
 
845
        if (mode & 1)
 
846
        {
 
847
          end= strmov(end, compatible_mode_names[i]);
 
848
          end= strmov(end, ",");
 
849
        }
 
850
      }
 
851
      if (end!=compatible_mode_normal_str)
 
852
        end[-1]= 0;
 
853
      /*
 
854
        Set charset to the default compiled value if it hasn't
 
855
        been reset yet by --default-character-set=xxx.
 
856
      */
 
857
      if (default_charset == mysql_universal_client_charset)
 
858
        default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
 
859
      break;
 
860
    }
 
861
  case (int) OPT_MYSQL_PROTOCOL:
 
862
    opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
 
863
                                    opt->name);
 
864
    break;
 
865
  }
 
866
  return 0;
 
867
}
 
868
 
 
869
static int get_options(int *argc, char ***argv)
 
870
{
 
871
  int ho_error;
 
872
  MYSQL_PARAMETERS *mysql_params= mysql_get_parameters();
 
873
 
 
874
  opt_max_allowed_packet= *mysql_params->p_max_allowed_packet;
 
875
  opt_net_buffer_length= *mysql_params->p_net_buffer_length;
 
876
 
 
877
  md_result_file= stdout;
 
878
  load_defaults("my",load_default_groups,argc,argv);
 
879
  defaults_argv= *argv;
 
880
 
 
881
  if (hash_init(&ignore_table, charset_info, 16, 0, 0,
 
882
                (hash_get_key) get_table_key,
 
883
                (hash_free_key) free_table_ent, 0))
 
884
    return(EX_EOM);
 
885
  /* Don't copy internal log tables */
 
886
  if (my_hash_insert(&ignore_table,
 
887
                     (uchar*) my_strdup("mysql.apply_status", MYF(MY_WME))) ||
 
888
      my_hash_insert(&ignore_table,
 
889
                     (uchar*) my_strdup("mysql.schema", MYF(MY_WME))) ||
 
890
      my_hash_insert(&ignore_table,
 
891
                     (uchar*) my_strdup("mysql.general_log", MYF(MY_WME))) ||
 
892
      my_hash_insert(&ignore_table,
 
893
                     (uchar*) my_strdup("mysql.slow_log", MYF(MY_WME))) ||
 
894
      my_hash_insert(&ignore_table,
 
895
                     (uchar*) my_strdup("mysql.online_backup", MYF(MY_WME))) ||
 
896
      my_hash_insert(&ignore_table,
 
897
                     (uchar*) my_strdup("mysql.online_backup_progress", MYF(MY_WME))))
 
898
    return(EX_EOM);
 
899
 
 
900
  if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
 
901
    return(ho_error);
 
902
 
 
903
  *mysql_params->p_max_allowed_packet= opt_max_allowed_packet;
 
904
  *mysql_params->p_net_buffer_length= opt_net_buffer_length;
 
905
  if (debug_info_flag)
 
906
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
 
907
  if (debug_check_flag)
 
908
    my_end_arg= MY_CHECK_ERROR;
 
909
 
 
910
  if (opt_delayed)
 
911
    opt_lock=0;                         /* Can't have lock with delayed */
 
912
  if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
 
913
                fields_terminated))
 
914
  {
 
915
    fprintf(stderr,
 
916
            "%s: You must use option --tab with --fields-...\n", my_progname);
 
917
    return(EX_USAGE);
 
918
  }
 
919
 
 
920
  /* We don't delete master logs if slave data option */
 
921
  if (opt_slave_data)
 
922
  {
 
923
    opt_lock_all_tables= !opt_single_transaction;
 
924
    opt_master_data= 0;
 
925
    opt_delete_master_logs= 0;
 
926
  }
 
927
 
 
928
  /* Ensure consistency of the set of binlog & locking options */
 
929
  if (opt_delete_master_logs && !opt_master_data)
 
930
    opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL;
 
931
  if (opt_single_transaction && opt_lock_all_tables)
 
932
  {
 
933
    fprintf(stderr, "%s: You can't use --single-transaction and "
 
934
            "--lock-all-tables at the same time.\n", my_progname);
 
935
    return(EX_USAGE);
 
936
  }
 
937
  if (opt_master_data)
 
938
  {
 
939
    opt_lock_all_tables= !opt_single_transaction;
 
940
    opt_slave_data= 0;
 
941
  }
 
942
  if (opt_single_transaction || opt_lock_all_tables)
 
943
    lock_tables= 0;
 
944
  if (enclosed && opt_enclosed)
 
945
  {
 
946
    fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
 
947
    return(EX_USAGE);
 
948
  }
 
949
  if ((opt_databases || opt_alldbs) && path)
 
950
  {
 
951
    fprintf(stderr,
 
952
            "%s: --databases or --all-databases can't be used with --tab.\n",
 
953
            my_progname);
 
954
    return(EX_USAGE);
 
955
  }
 
956
  if (strcmp(default_charset, charset_info->csname) &&
 
957
      !(charset_info= get_charset_by_csname(default_charset,
 
958
                                            MY_CS_PRIMARY, MYF(MY_WME))))
 
959
    exit(1);
 
960
  if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
 
961
  {
 
962
    short_usage();
 
963
    return EX_USAGE;
 
964
  }
 
965
  if (tty_password)
 
966
    opt_password=get_tty_password(NullS);
 
967
  return(0);
 
968
} /* get_options */
 
969
 
 
970
 
 
971
/*
 
972
** DB_error -- prints mysql error message and exits the program.
 
973
*/
 
974
static void DB_error(MYSQL *mysql_arg, const char *when)
 
975
{
 
976
  DBUG_ENTER("DB_error");
 
977
  maybe_die(EX_MYSQLERR, "Got error: %d: %s %s",
 
978
          mysql_errno(mysql_arg), mysql_error(mysql_arg), when);
 
979
  DBUG_VOID_RETURN;
 
980
}
 
981
 
 
982
 
 
983
 
 
984
/*
 
985
  Prints out an error message and kills the process.
 
986
 
 
987
  SYNOPSIS
 
988
    die()
 
989
    error_num   - process return value
 
990
    fmt_reason  - a format string for use by my_vsnprintf.
 
991
    ...         - variable arguments for above fmt_reason string
 
992
  
 
993
  DESCRIPTION
 
994
    This call prints out the formatted error message to stderr and then
 
995
    terminates the process.
 
996
*/
 
997
static void die(int error_num, const char* fmt_reason, ...)
 
998
{
 
999
  char buffer[1000];
 
1000
  va_list args;
 
1001
  va_start(args,fmt_reason);
 
1002
  my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
 
1003
  va_end(args);
 
1004
 
 
1005
  fprintf(stderr, "%s: %s\n", my_progname, buffer);
 
1006
  fflush(stderr);
 
1007
 
 
1008
  ignore_errors= 0; /* force the exit */
 
1009
  maybe_exit(error_num);
 
1010
}
 
1011
 
 
1012
 
 
1013
/*
 
1014
  Prints out an error message and maybe kills the process.
 
1015
 
 
1016
  SYNOPSIS
 
1017
    maybe_die()
 
1018
    error_num   - process return value
 
1019
    fmt_reason  - a format string for use by my_vsnprintf.
 
1020
    ...         - variable arguments for above fmt_reason string
 
1021
  
 
1022
  DESCRIPTION
 
1023
    This call prints out the formatted error message to stderr and then
 
1024
    terminates the process, unless the --force command line option is used.
 
1025
    
 
1026
    This call should be used for non-fatal errors (such as database
 
1027
    errors) that the code may still be able to continue to the next unit
 
1028
    of work.
 
1029
    
 
1030
*/
 
1031
static void maybe_die(int error_num, const char* fmt_reason, ...)
 
1032
{
 
1033
  char buffer[1000];
 
1034
  va_list args;
 
1035
  va_start(args,fmt_reason);
 
1036
  my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
 
1037
  va_end(args);
 
1038
 
 
1039
  fprintf(stderr, "%s: %s\n", my_progname, buffer);
 
1040
  fflush(stderr);
 
1041
 
 
1042
  maybe_exit(error_num);
 
1043
}
 
1044
 
 
1045
 
 
1046
 
 
1047
/*
 
1048
  Sends a query to server, optionally reads result, prints error message if
 
1049
  some.
 
1050
 
 
1051
  SYNOPSIS
 
1052
    mysql_query_with_error_report()
 
1053
    mysql_con       connection to use
 
1054
    res             if non zero, result will be put there with
 
1055
                    mysql_store_result()
 
1056
    query           query to send to server
 
1057
 
 
1058
  RETURN VALUES
 
1059
    0               query sending and (if res!=0) result reading went ok
 
1060
    1               error
 
1061
*/
 
1062
 
 
1063
static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res,
 
1064
                                         const char *query)
 
1065
{
 
1066
  if (mysql_query(mysql_con, query) ||
 
1067
      (res && !((*res)= mysql_store_result(mysql_con))))
 
1068
  {
 
1069
    maybe_die(EX_MYSQLERR, "Couldn't execute '%s': %s (%d)",
 
1070
            query, mysql_error(mysql_con), mysql_errno(mysql_con));
 
1071
    return 1;
 
1072
  }
 
1073
  return 0;
 
1074
}
 
1075
 
 
1076
 
 
1077
static int fetch_db_collation(const char *db_name,
 
1078
                              char *db_cl_name,
 
1079
                              int db_cl_size)
 
1080
{
 
1081
  my_bool err_status= FALSE;
 
1082
  char query[QUERY_LENGTH];
 
1083
  MYSQL_RES *db_cl_res;
 
1084
  MYSQL_ROW db_cl_row;
 
1085
  char quoted_database_buf[NAME_LEN*2+3];
 
1086
  char *qdatabase= quote_name(db_name, quoted_database_buf, 1);
 
1087
 
 
1088
  my_snprintf(query, sizeof (query), "use %s", qdatabase);
 
1089
 
 
1090
  if (mysql_query_with_error_report(mysql, NULL, query))
 
1091
    return 1;
 
1092
 
 
1093
  if (mysql_query_with_error_report(mysql, &db_cl_res,
 
1094
                                    "select @@collation_database"))
 
1095
    return 1;
 
1096
 
 
1097
  do
 
1098
  {
 
1099
    if (mysql_num_rows(db_cl_res) != 1)
 
1100
    {
 
1101
      err_status= TRUE;
 
1102
      break;
 
1103
    }
 
1104
 
 
1105
    if (!(db_cl_row= mysql_fetch_row(db_cl_res)))
 
1106
    {
 
1107
      err_status= TRUE;
 
1108
      break;
 
1109
    }
 
1110
 
 
1111
    strncpy(db_cl_name, db_cl_row[0], db_cl_size);
 
1112
    db_cl_name[db_cl_size - 1]= 0; /* just in case. */
 
1113
 
 
1114
  } while (FALSE);
 
1115
 
 
1116
  mysql_free_result(db_cl_res);
 
1117
 
 
1118
  return err_status ? 1 : 0;
 
1119
}
 
1120
 
 
1121
 
 
1122
static char *my_case_str(const char *str,
 
1123
                         uint str_len,
 
1124
                         const char *token,
 
1125
                         uint token_len)
 
1126
{
 
1127
  my_match_t match;
 
1128
 
 
1129
  uint status= my_charset_latin1.coll->instr(&my_charset_latin1,
 
1130
                                             str, str_len,
 
1131
                                             token, token_len,
 
1132
                                             &match, 1);
 
1133
 
 
1134
  return status ? (char *) str + match.end : NULL;
 
1135
}
 
1136
 
 
1137
 
 
1138
static int switch_db_collation(FILE *sql_file,
 
1139
                               const char *db_name,
 
1140
                               const char *delimiter,
 
1141
                               const char *current_db_cl_name,
 
1142
                               const char *required_db_cl_name,
 
1143
                               int *db_cl_altered)
 
1144
{
 
1145
  if (strcmp(current_db_cl_name, required_db_cl_name) != 0)
 
1146
  {
 
1147
    CHARSET_INFO *db_cl= get_charset_by_name(required_db_cl_name, MYF(0));
 
1148
 
 
1149
    if (!db_cl)
 
1150
      return 1;
 
1151
 
 
1152
    fprintf(sql_file,
 
1153
            "ALTER DATABASE %s CHARACTER SET %s COLLATE %s %s\n",
 
1154
            (const char *) db_name,
 
1155
            (const char *) db_cl->csname,
 
1156
            (const char *) db_cl->name,
 
1157
            (const char *) delimiter);
 
1158
 
 
1159
    *db_cl_altered= 1;
 
1160
 
 
1161
    return 0;
 
1162
  }
 
1163
 
 
1164
  *db_cl_altered= 0;
 
1165
 
 
1166
  return 0;
 
1167
}
 
1168
 
 
1169
 
 
1170
static int restore_db_collation(FILE *sql_file,
 
1171
                                const char *db_name,
 
1172
                                const char *delimiter,
 
1173
                                const char *db_cl_name)
 
1174
{
 
1175
  CHARSET_INFO *db_cl= get_charset_by_name(db_cl_name, MYF(0));
 
1176
 
 
1177
  if (!db_cl)
 
1178
    return 1;
 
1179
 
 
1180
  fprintf(sql_file,
 
1181
          "ALTER DATABASE %s CHARACTER SET %s COLLATE %s %s\n",
 
1182
          (const char *) db_name,
 
1183
          (const char *) db_cl->csname,
 
1184
          (const char *) db_cl->name,
 
1185
          (const char *) delimiter);
 
1186
 
 
1187
  return 0;
 
1188
}
 
1189
 
 
1190
 
 
1191
static void switch_cs_variables(FILE *sql_file,
 
1192
                                const char *delimiter,
 
1193
                                const char *character_set_client,
 
1194
                                const char *character_set_results,
 
1195
                                const char *collation_connection)
 
1196
{
 
1197
  fprintf(sql_file,
 
1198
          "/*!50003 SET @saved_cs_client      = @@character_set_client */ %s\n"
 
1199
          "/*!50003 SET @saved_cs_results     = @@character_set_results */ %s\n"
 
1200
          "/*!50003 SET @saved_col_connection = @@collation_connection */ %s\n"
 
1201
          "/*!50003 SET character_set_client  = %s */ %s\n"
 
1202
          "/*!50003 SET character_set_results = %s */ %s\n"
 
1203
          "/*!50003 SET collation_connection  = %s */ %s\n",
 
1204
          (const char *) delimiter,
 
1205
          (const char *) delimiter,
 
1206
          (const char *) delimiter,
 
1207
 
 
1208
          (const char *) character_set_client,
 
1209
          (const char *) delimiter,
 
1210
 
 
1211
          (const char *) character_set_results,
 
1212
          (const char *) delimiter,
 
1213
 
 
1214
          (const char *) collation_connection,
 
1215
          (const char *) delimiter);
 
1216
}
 
1217
 
 
1218
 
 
1219
static void restore_cs_variables(FILE *sql_file,
 
1220
                                 const char *delimiter)
 
1221
{
 
1222
  fprintf(sql_file,
 
1223
          "/*!50003 SET character_set_client  = @saved_cs_client */ %s\n"
 
1224
          "/*!50003 SET character_set_results = @saved_cs_results */ %s\n"
 
1225
          "/*!50003 SET collation_connection  = @saved_col_connection */ %s\n",
 
1226
          (const char *) delimiter,
 
1227
          (const char *) delimiter,
 
1228
          (const char *) delimiter);
 
1229
}
 
1230
 
 
1231
 
 
1232
static void switch_sql_mode(FILE *sql_file,
 
1233
                            const char *delimiter,
 
1234
                            const char *sql_mode)
 
1235
{
 
1236
  fprintf(sql_file,
 
1237
          "/*!50003 SET @saved_sql_mode       = @@sql_mode */ %s\n"
 
1238
          "/*!50003 SET sql_mode              = '%s' */ %s\n",
 
1239
          (const char *) delimiter,
 
1240
 
 
1241
          (const char *) sql_mode,
 
1242
          (const char *) delimiter);
 
1243
}
 
1244
 
 
1245
 
 
1246
static void restore_sql_mode(FILE *sql_file,
 
1247
                             const char *delimiter)
 
1248
{
 
1249
  fprintf(sql_file,
 
1250
          "/*!50003 SET sql_mode              = @saved_sql_mode */ %s\n",
 
1251
          (const char *) delimiter);
 
1252
}
 
1253
 
 
1254
 
 
1255
static void switch_time_zone(FILE *sql_file,
 
1256
                             const char *delimiter,
 
1257
                             const char *time_zone)
 
1258
{
 
1259
  fprintf(sql_file,
 
1260
          "/*!50003 SET @saved_time_zone      = @@time_zone */ %s\n"
 
1261
          "/*!50003 SET time_zone             = '%s' */ %s\n",
 
1262
          (const char *) delimiter,
 
1263
 
 
1264
          (const char *) time_zone,
 
1265
          (const char *) delimiter);
 
1266
}
 
1267
 
 
1268
 
 
1269
static void restore_time_zone(FILE *sql_file,
 
1270
                              const char *delimiter)
 
1271
{
 
1272
  fprintf(sql_file,
 
1273
          "/*!50003 SET time_zone             = @saved_time_zone */ %s\n",
 
1274
          (const char *) delimiter);
 
1275
}
 
1276
 
 
1277
 
 
1278
/**
 
1279
  Switch charset for results to some specified charset.  If the server does not
 
1280
  support character_set_results variable, nothing can be done here.  As for
 
1281
  whether something should be done here, future new callers of this function
 
1282
  should be aware that the server lacking the facility of switching charsets is
 
1283
  treated as success.
 
1284
 
 
1285
  @note  If the server lacks support, then nothing is changed and no error
 
1286
         condition is returned.
 
1287
 
 
1288
  @returns  whether there was an error or not
 
1289
*/
 
1290
static int switch_character_set_results(MYSQL *mysql, const char *cs_name)
 
1291
{
 
1292
  char query_buffer[QUERY_LENGTH];
 
1293
  size_t query_length;
 
1294
 
 
1295
  /* Server lacks facility.  This is not an error, by arbitrary decision . */
 
1296
  if (!server_supports_switching_charsets)
 
1297
    return FALSE;
 
1298
 
 
1299
  query_length= my_snprintf(query_buffer,
 
1300
                            sizeof (query_buffer),
 
1301
                            "SET SESSION character_set_results = '%s'",
 
1302
                            (const char *) cs_name);
 
1303
 
 
1304
  return mysql_real_query(mysql, query_buffer, query_length);
 
1305
}
 
1306
 
 
1307
/**
 
1308
  Rewrite CREATE FUNCTION or CREATE PROCEDURE statement, enclosing DEFINER
 
1309
  clause in version-specific comment.
 
1310
 
 
1311
  This function parses the CREATE FUNCTION | PROCEDURE statement and
 
1312
  encloses DEFINER-clause in version-specific comment:
 
1313
    input query:     CREATE DEFINER=a@b FUNCTION ...
 
1314
    rewritten query: CREATE * / / *!50020 DEFINER=a@b * / / *!50003 FUNCTION ...
 
1315
 
 
1316
  @note This function will go away when WL#3995 is implemented.
 
1317
 
 
1318
  @param[in] def_str        CREATE FUNCTION|PROCEDURE statement string.
 
1319
  @param[in] def_str_length length of the def_str.
 
1320
 
 
1321
  @return pointer to the new allocated query string.
 
1322
*/
 
1323
 
 
1324
static char *cover_definer_clause_in_sp(const char *def_str,
 
1325
                                        uint def_str_length)
 
1326
{
 
1327
  char *query_str= NULL;
 
1328
  char *definer_begin= my_case_str(def_str, def_str_length,
 
1329
                                   C_STRING_WITH_LEN(" DEFINER"));
 
1330
  char *definer_end;
 
1331
 
 
1332
  if (!definer_begin)
 
1333
    return NULL;
 
1334
 
 
1335
  definer_end= my_case_str(definer_begin, strlen(definer_begin),
 
1336
                           C_STRING_WITH_LEN(" PROCEDURE"));
 
1337
 
 
1338
  if (!definer_end)
 
1339
  {
 
1340
    definer_end= my_case_str(definer_begin, strlen(definer_begin),
 
1341
                             C_STRING_WITH_LEN(" FUNCTION"));
 
1342
  }
 
1343
 
 
1344
  if (definer_end)
 
1345
  {
 
1346
    char *query_str_tail;
 
1347
 
 
1348
    /*
 
1349
      Allocate memory for new query string: original string
 
1350
      from SHOW statement and version-specific comments.
 
1351
    */
 
1352
    query_str= alloc_query_str(def_str_length + 23);
 
1353
 
 
1354
    query_str_tail= strnmov(query_str, def_str, definer_begin - def_str);
 
1355
    query_str_tail= strmov(query_str_tail, "*/ /*!50020");
 
1356
    query_str_tail= strnmov(query_str_tail, definer_begin,
 
1357
                            definer_end - definer_begin);
 
1358
    query_str_tail= strxmov(query_str_tail, "*/ /*!50003",
 
1359
                            definer_end, NullS);
 
1360
  }
 
1361
 
 
1362
  return query_str;
 
1363
}
 
1364
 
 
1365
/*
 
1366
  Open a new .sql file to dump the table or view into
 
1367
 
 
1368
  SYNOPSIS
 
1369
    open_sql_file_for_table
 
1370
    name      name of the table or view
 
1371
 
 
1372
  RETURN VALUES
 
1373
    0        Failed to open file
 
1374
    > 0      Handle of the open file
 
1375
*/
 
1376
static FILE* open_sql_file_for_table(const char* table)
 
1377
{
 
1378
  FILE* res;
 
1379
  char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
1380
  convert_dirname(tmp_path,path,NullS);
 
1381
  res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
 
1382
                O_WRONLY, MYF(MY_WME));
 
1383
  return res;
 
1384
}
 
1385
 
 
1386
 
 
1387
static void free_resources()
 
1388
{
 
1389
  if (md_result_file && md_result_file != stdout)
 
1390
    my_fclose(md_result_file, MYF(0));
 
1391
  my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
 
1392
  if (hash_inited(&ignore_table))
 
1393
    hash_free(&ignore_table);
 
1394
  if (extended_insert)
 
1395
    dynstr_free(&extended_row);
 
1396
  if (insert_pat_inited)
 
1397
    dynstr_free(&insert_pat);
 
1398
  if (defaults_argv)
 
1399
    free_defaults(defaults_argv);
 
1400
  my_end(my_end_arg);
 
1401
}
 
1402
 
 
1403
 
 
1404
static void maybe_exit(int error)
 
1405
{
 
1406
  if (!first_error)
 
1407
    first_error= error;
 
1408
  if (ignore_errors)
 
1409
    return;
 
1410
  if (mysql)
 
1411
    mysql_close(mysql);
 
1412
  free_resources();
 
1413
  exit(error);
 
1414
}
 
1415
 
 
1416
 
 
1417
/*
 
1418
  db_connect -- connects to the host and selects DB.
 
1419
*/
 
1420
 
 
1421
static int connect_to_db(char *host, char *user,char *passwd)
 
1422
{
 
1423
  char buff[20+FN_REFLEN];
 
1424
  DBUG_ENTER("connect_to_db");
 
1425
 
 
1426
  verbose_msg("-- Connecting to %s...\n", host ? host : "localhost");
 
1427
  mysql_init(&mysql_connection);
 
1428
  if (opt_compress)
 
1429
    mysql_options(&mysql_connection,MYSQL_OPT_COMPRESS,NullS);
 
1430
#ifdef HAVE_OPENSSL
 
1431
  if (opt_use_ssl)
 
1432
    mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
 
1433
                  opt_ssl_capath, opt_ssl_cipher);
 
1434
  mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
 
1435
                (char*)&opt_ssl_verify_server_cert);
 
1436
#endif
 
1437
  if (opt_protocol)
 
1438
    mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 
1439
#ifdef HAVE_SMEM
 
1440
  if (shared_memory_base_name)
 
1441
    mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
 
1442
#endif
 
1443
  mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
 
1444
  if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd,
 
1445
                                  NULL,opt_mysql_port,opt_mysql_unix_port,
 
1446
                                  0)))
 
1447
  {
 
1448
    DB_error(&mysql_connection, "when trying to connect");
 
1449
    DBUG_RETURN(1);
 
1450
  }
 
1451
  if (mysql_get_server_version(&mysql_connection) < 40100)
 
1452
  {
 
1453
    /* Don't dump SET NAMES with a pre-4.1 server (bug#7997).  */
 
1454
    opt_set_charset= 0;
 
1455
 
 
1456
    /* Don't switch charsets for 4.1 and earlier.  (bug#34192). */
 
1457
    server_supports_switching_charsets= FALSE;
 
1458
  } 
 
1459
  /*
 
1460
    set time_zone to UTC to allow dumping date types between servers with
 
1461
    different time zone settings
 
1462
  */
 
1463
  if (opt_tz_utc)
 
1464
  {
 
1465
    my_snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */");
 
1466
    if (mysql_query_with_error_report(mysql, 0, buff))
 
1467
      DBUG_RETURN(1);
 
1468
  }
 
1469
  DBUG_RETURN(0);
 
1470
} /* connect_to_db */
 
1471
 
 
1472
 
 
1473
/*
 
1474
** dbDisconnect -- disconnects from the host.
 
1475
*/
 
1476
static void dbDisconnect(char *host)
 
1477
{
 
1478
  verbose_msg("-- Disconnecting from %s...\n", host ? host : "localhost");
 
1479
  mysql_close(mysql);
 
1480
} /* dbDisconnect */
 
1481
 
 
1482
 
 
1483
static void unescape(FILE *file,char *pos,uint length)
 
1484
{
 
1485
  char *tmp;
 
1486
  DBUG_ENTER("unescape");
 
1487
  if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
 
1488
    die(EX_MYSQLERR, "Couldn't allocate memory");
 
1489
 
 
1490
  mysql_real_escape_string(&mysql_connection, tmp, pos, length);
 
1491
  fputc('\'', file);
 
1492
  fputs(tmp, file);
 
1493
  fputc('\'', file);
 
1494
  check_io(file);
 
1495
  my_free(tmp, MYF(MY_WME));
 
1496
  DBUG_VOID_RETURN;
 
1497
} /* unescape */
 
1498
 
 
1499
 
 
1500
static my_bool test_if_special_chars(const char *str)
 
1501
{
 
1502
#if MYSQL_VERSION_ID >= 32300
 
1503
  for ( ; *str ; str++)
 
1504
    if (!my_isvar(charset_info,*str) && *str != '$')
 
1505
      return 1;
 
1506
#endif
 
1507
  return 0;
 
1508
} /* test_if_special_chars */
 
1509
 
 
1510
 
 
1511
 
 
1512
/*
 
1513
  quote_name(name, buff, force)
 
1514
 
 
1515
  Quotes char string, taking into account compatible mode
 
1516
 
 
1517
  Args
 
1518
 
 
1519
  name                 Unquoted string containing that which will be quoted
 
1520
  buff                 The buffer that contains the quoted value, also returned
 
1521
  force                Flag to make it ignore 'test_if_special_chars'
 
1522
 
 
1523
  Returns
 
1524
 
 
1525
  buff                 quoted string
 
1526
 
 
1527
*/
 
1528
static char *quote_name(const char *name, char *buff, my_bool force)
 
1529
{
 
1530
  char *to= buff;
 
1531
  char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';
 
1532
 
 
1533
  if (!force && !opt_quoted && !test_if_special_chars(name))
 
1534
    return (char*) name;
 
1535
  *to++= qtype;
 
1536
  while (*name)
 
1537
  {
 
1538
    if (*name == qtype)
 
1539
      *to++= qtype;
 
1540
    *to++= *name++;
 
1541
  }
 
1542
  to[0]= qtype;
 
1543
  to[1]= 0;
 
1544
  return buff;
 
1545
} /* quote_name */
 
1546
 
 
1547
 
 
1548
/*
 
1549
  Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
 
1550
 
 
1551
  SYNOPSIS
 
1552
    quote_for_like()
 
1553
    name     name of the table
 
1554
    buff     quoted name of the table
 
1555
 
 
1556
  DESCRIPTION
 
1557
    Quote \, _, ' and % characters
 
1558
 
 
1559
    Note: Because MySQL uses the C escape syntax in strings
 
1560
    (for example, '\n' to represent newline), you must double
 
1561
    any '\' that you use in your LIKE  strings. For example, to
 
1562
    search for '\n', specify it as '\\n'. To search for '\', specify
 
1563
    it as '\\\\' (the backslashes are stripped once by the parser
 
1564
    and another time when the pattern match is done, leaving a
 
1565
    single backslash to be matched).
 
1566
 
 
1567
    Example: "t\1" => "t\\\\1"
 
1568
 
 
1569
*/
 
1570
static char *quote_for_like(const char *name, char *buff)
 
1571
{
 
1572
  char *to= buff;
 
1573
  *to++= '\'';
 
1574
  while (*name)
 
1575
  {
 
1576
    if (*name == '\\')
 
1577
    {
 
1578
      *to++='\\';
 
1579
      *to++='\\';
 
1580
      *to++='\\';
 
1581
    }
 
1582
    else if (*name == '\'' || *name == '_'  || *name == '%')
 
1583
      *to++= '\\';
 
1584
    *to++= *name++;
 
1585
  }
 
1586
  to[0]= '\'';
 
1587
  to[1]= 0;
 
1588
  return buff;
 
1589
}
 
1590
 
 
1591
 
 
1592
/*
 
1593
  Quote and print a string.
 
1594
 
 
1595
  SYNOPSIS
 
1596
    print_quoted_xml()
 
1597
    xml_file    - output file
 
1598
    str         - string to print
 
1599
    len         - its length
 
1600
 
 
1601
  DESCRIPTION
 
1602
    Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
 
1603
*/
 
1604
 
 
1605
static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
 
1606
{
 
1607
  const char *end;
 
1608
 
 
1609
  for (end= str + len; str != end; str++)
 
1610
  {
 
1611
    switch (*str) {
 
1612
    case '<':
 
1613
      fputs("&lt;", xml_file);
 
1614
      break;
 
1615
    case '>':
 
1616
      fputs("&gt;", xml_file);
 
1617
      break;
 
1618
    case '&':
 
1619
      fputs("&amp;", xml_file);
 
1620
      break;
 
1621
    case '\"':
 
1622
      fputs("&quot;", xml_file);
 
1623
      break;
 
1624
    default:
 
1625
      fputc(*str, xml_file);
 
1626
      break;
 
1627
    }
 
1628
  }
 
1629
  check_io(xml_file);
 
1630
}
 
1631
 
 
1632
 
 
1633
/*
 
1634
  Print xml tag. Optionally add attribute(s).
 
1635
 
 
1636
  SYNOPSIS
 
1637
    print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name, 
 
1638
                    ..., attribute_name_n, attribute_value_n, NullS)
 
1639
    xml_file              - output file
 
1640
    sbeg                  - line beginning
 
1641
    line_end              - line ending
 
1642
    tag_name              - XML tag name.
 
1643
    first_attribute_name  - tag and first attribute
 
1644
    first_attribute_value - (Implied) value of first attribute
 
1645
    attribute_name_n      - attribute n
 
1646
    attribute_value_n     - value of attribute n
 
1647
 
 
1648
  DESCRIPTION
 
1649
    Print XML tag with any number of attribute="value" pairs to the xml_file.
 
1650
 
 
1651
    Format is:
 
1652
      sbeg<tag_name first_attribute_name="first_attribute_value" ... 
 
1653
      attribute_name_n="attribute_value_n">send
 
1654
  NOTE
 
1655
    Additional arguments must be present in attribute/value pairs.
 
1656
    The last argument should be the null character pointer.
 
1657
    All attribute_value arguments MUST be NULL terminated strings.
 
1658
    All attribute_value arguments will be quoted before output.
 
1659
*/
 
1660
 
 
1661
static void print_xml_tag(FILE * xml_file, const char* sbeg,
 
1662
                          const char* line_end, 
 
1663
                          const char* tag_name, 
 
1664
                          const char* first_attribute_name, ...)
 
1665
{
 
1666
  va_list arg_list;
 
1667
  const char *attribute_name, *attribute_value;
 
1668
 
 
1669
  fputs(sbeg, xml_file);
 
1670
  fputc('<', xml_file);
 
1671
  fputs(tag_name, xml_file);  
 
1672
 
 
1673
  va_start(arg_list, first_attribute_name);
 
1674
  attribute_name= first_attribute_name;
 
1675
  while (attribute_name != NullS)
 
1676
  {
 
1677
    attribute_value= va_arg(arg_list, char *);
 
1678
    DBUG_ASSERT(attribute_value != NullS);
 
1679
 
 
1680
    fputc(' ', xml_file);
 
1681
    fputs(attribute_name, xml_file);    
 
1682
    fputc('\"', xml_file);
 
1683
    
 
1684
    print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
 
1685
    fputc('\"', xml_file);
 
1686
 
 
1687
    attribute_name= va_arg(arg_list, char *);
 
1688
  }
 
1689
  va_end(arg_list);
 
1690
 
 
1691
  fputc('>', xml_file);
 
1692
  fputs(line_end, xml_file);
 
1693
  check_io(xml_file);
 
1694
}
 
1695
 
 
1696
 
 
1697
/*
 
1698
  Print xml tag with for a field that is null
 
1699
 
 
1700
  SYNOPSIS
 
1701
    print_xml_null_tag()
 
1702
    xml_file    - output file
 
1703
    sbeg        - line beginning
 
1704
    stag_atr    - tag and attribute
 
1705
    sval        - value of attribute
 
1706
    line_end        - line ending
 
1707
 
 
1708
  DESCRIPTION
 
1709
    Print tag with one attribute to the xml_file. Format is:
 
1710
      <stag_atr="sval" xsi:nil="true"/>
 
1711
  NOTE
 
1712
    sval MUST be a NULL terminated string.
 
1713
    sval string will be qouted before output.
 
1714
*/
 
1715
 
 
1716
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
 
1717
                               const char* stag_atr, const char* sval,
 
1718
                               const char* line_end)
 
1719
{
 
1720
  fputs(sbeg, xml_file);
 
1721
  fputs("<", xml_file);
 
1722
  fputs(stag_atr, xml_file);
 
1723
  fputs("\"", xml_file);
 
1724
  print_quoted_xml(xml_file, sval, strlen(sval));
 
1725
  fputs("\" xsi:nil=\"true\" />", xml_file);
 
1726
  fputs(line_end, xml_file);
 
1727
  check_io(xml_file);
 
1728
}
 
1729
 
 
1730
 
 
1731
/*
 
1732
  Print xml tag with many attributes.
 
1733
 
 
1734
  SYNOPSIS
 
1735
    print_xml_row()
 
1736
    xml_file    - output file
 
1737
    row_name    - xml tag name
 
1738
    tableRes    - query result
 
1739
    row         - result row
 
1740
 
 
1741
  DESCRIPTION
 
1742
    Print tag with many attribute to the xml_file. Format is:
 
1743
      \t\t<row_name Atr1="Val1" Atr2="Val2"... />
 
1744
  NOTE
 
1745
    All atributes and values will be quoted before output.
 
1746
*/
 
1747
 
 
1748
static void print_xml_row(FILE *xml_file, const char *row_name,
 
1749
                          MYSQL_RES *tableRes, MYSQL_ROW *row)
 
1750
{
 
1751
  uint i;
 
1752
  MYSQL_FIELD *field;
 
1753
  ulong *lengths= mysql_fetch_lengths(tableRes);
 
1754
 
 
1755
  fprintf(xml_file, "\t\t<%s", row_name);
 
1756
  check_io(xml_file);
 
1757
  mysql_field_seek(tableRes, 0);
 
1758
  for (i= 0; (field= mysql_fetch_field(tableRes)); i++)
 
1759
  {
 
1760
    if ((*row)[i])
 
1761
    {
 
1762
      fputc(' ', xml_file);
 
1763
      print_quoted_xml(xml_file, field->name, field->name_length);
 
1764
      fputs("=\"", xml_file);
 
1765
      print_quoted_xml(xml_file, (*row)[i], lengths[i]);
 
1766
      fputc('"', xml_file);
 
1767
      check_io(xml_file);
 
1768
    }
 
1769
  }
 
1770
  fputs(" />\n", xml_file);
 
1771
  check_io(xml_file);
 
1772
}
 
1773
 
 
1774
 
 
1775
/*
 
1776
 create_delimiter
 
1777
 Generate a new (null-terminated) string that does not exist in  query 
 
1778
 and is therefore suitable for use as a query delimiter.  Store this
 
1779
 delimiter in  delimiter_buff .
 
1780
 
 
1781
 This is quite simple in that it doesn't even try to parse statements as an
 
1782
 interpreter would.  It merely returns a string that is not in the query, which
 
1783
 is much more than adequate for constructing a delimiter.
 
1784
 
 
1785
 RETURN
 
1786
   ptr to the delimiter  on Success
 
1787
   NULL                  on Failure
 
1788
*/
 
1789
static char *create_delimiter(char *query, char *delimiter_buff, 
 
1790
                              int delimiter_max_size) 
 
1791
{
 
1792
  int proposed_length;
 
1793
  char *presence;
 
1794
 
 
1795
  delimiter_buff[0]= ';';  /* start with one semicolon, and */
 
1796
 
 
1797
  for (proposed_length= 2; proposed_length < delimiter_max_size; 
 
1798
      delimiter_max_size++) {
 
1799
 
 
1800
    delimiter_buff[proposed_length-1]= ';';  /* add semicolons, until */
 
1801
    delimiter_buff[proposed_length]= '\0';
 
1802
 
 
1803
    presence = strstr(query, delimiter_buff);
 
1804
    if (presence == NULL) { /* the proposed delimiter is not in the query. */
 
1805
       return delimiter_buff;
 
1806
    }
 
1807
 
 
1808
  }
 
1809
  return NULL;  /* but if we run out of space, return nothing at all. */
 
1810
}
 
1811
 
 
1812
 
 
1813
/*
 
1814
  dump_events_for_db
 
1815
  -- retrieves list of events for a given db, and prints out
 
1816
  the CREATE EVENT statement into the output (the dump).
 
1817
 
 
1818
  RETURN
 
1819
    0  Success
 
1820
    1  Error
 
1821
*/
 
1822
static uint dump_events_for_db(char *db)
 
1823
{
 
1824
  char       query_buff[QUERY_LENGTH];
 
1825
  char       db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
 
1826
  char       *event_name;
 
1827
  char       delimiter[QUERY_LENGTH];
 
1828
  FILE       *sql_file= md_result_file;
 
1829
  MYSQL_RES  *event_res, *event_list_res;
 
1830
  MYSQL_ROW  row, event_list_row;
 
1831
 
 
1832
  char       db_cl_name[MY_CS_NAME_SIZE];
 
1833
  int        db_cl_altered= FALSE;
 
1834
 
 
1835
  DBUG_ENTER("dump_events_for_db");
 
1836
  DBUG_PRINT("enter", ("db: '%s'", db));
 
1837
 
 
1838
  mysql_real_escape_string(mysql, db_name_buff, db, strlen(db));
 
1839
 
 
1840
  /* nice comments */
 
1841
  if (opt_comments)
 
1842
    fprintf(sql_file, "\n--\n-- Dumping events for database '%s'\n--\n", db);
 
1843
 
 
1844
  /*
 
1845
    not using "mysql_query_with_error_report" because we may have not
 
1846
    enough privileges to lock mysql.events.
 
1847
  */
 
1848
  if (lock_tables)
 
1849
    mysql_query(mysql, "LOCK TABLES mysql.event READ");
 
1850
 
 
1851
  if (mysql_query_with_error_report(mysql, &event_list_res, "show events"))
 
1852
    DBUG_RETURN(0);
 
1853
 
 
1854
  strcpy(delimiter, ";");
 
1855
  if (mysql_num_rows(event_list_res) > 0)
 
1856
  {
 
1857
    fprintf(sql_file, "/*!50106 SET @save_time_zone= @@TIME_ZONE */ ;\n");
 
1858
 
 
1859
    /* Get database collation. */
 
1860
 
 
1861
    if (fetch_db_collation(db_name_buff, db_cl_name, sizeof (db_cl_name)))
 
1862
      DBUG_RETURN(1);
 
1863
 
 
1864
    if (switch_character_set_results(mysql, "binary"))
 
1865
      DBUG_RETURN(1);
 
1866
 
 
1867
    while ((event_list_row= mysql_fetch_row(event_list_res)) != NULL)
 
1868
    {
 
1869
      event_name= quote_name(event_list_row[1], name_buff, 0);
 
1870
      DBUG_PRINT("info", ("retrieving CREATE EVENT for %s", name_buff));
 
1871
      my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE EVENT %s", 
 
1872
          event_name);
 
1873
 
 
1874
      if (mysql_query_with_error_report(mysql, &event_res, query_buff))
 
1875
        DBUG_RETURN(1);
 
1876
 
 
1877
      while ((row= mysql_fetch_row(event_res)) != NULL)
 
1878
      {
 
1879
        /*
 
1880
          if the user has EXECUTE privilege he can see event names, but not the
 
1881
          event body!
 
1882
        */
 
1883
        if (strlen(row[3]) != 0)
 
1884
        {
 
1885
          if (opt_drop)
 
1886
            fprintf(sql_file, "/*!50106 DROP EVENT IF EXISTS %s */%s\n", 
 
1887
                event_name, delimiter);
 
1888
 
 
1889
          if (create_delimiter(row[3], delimiter, sizeof(delimiter)) == NULL)
 
1890
          {
 
1891
            fprintf(stderr, "%s: Warning: Can't create delimiter for event '%s'\n",
 
1892
                    my_progname, event_name);
 
1893
            DBUG_RETURN(1);
 
1894
          }
 
1895
 
 
1896
          fprintf(sql_file, "DELIMITER %s\n", delimiter);
 
1897
 
 
1898
          if (mysql_num_fields(event_res) >= 7)
 
1899
          {
 
1900
            if (switch_db_collation(sql_file, db_name_buff, delimiter,
 
1901
                                    db_cl_name, row[6], &db_cl_altered))
 
1902
            {
 
1903
              DBUG_RETURN(1);
 
1904
            }
 
1905
 
 
1906
            switch_cs_variables(sql_file, delimiter,
 
1907
                                row[4],   /* character_set_client */
 
1908
                                row[4],   /* character_set_results */
 
1909
                                row[5]);  /* collation_connection */
 
1910
          }
 
1911
            else
 
1912
            {
 
1913
              /*
 
1914
                mysqldump is being run against the server, that does not
 
1915
                provide character set information in SHOW CREATE
 
1916
                statements.
 
1917
 
 
1918
                NOTE: the dump may be incorrect, since character set
 
1919
                information is required in order to restore event properly.
 
1920
              */
 
1921
 
 
1922
              fprintf(sql_file,
 
1923
                      "--\n"
 
1924
                      "-- WARNING: old server version. "
 
1925
                        "The following dump may be incomplete.\n"
 
1926
                      "--\n");
 
1927
            }
 
1928
 
 
1929
          switch_sql_mode(sql_file, delimiter, row[1]);
 
1930
 
 
1931
          switch_time_zone(sql_file, delimiter, row[2]);
 
1932
 
 
1933
          fprintf(sql_file,
 
1934
                  "/*!50106 %s */ %s\n",
 
1935
                  (const char *) row[3],
 
1936
                  (const char *) delimiter);
 
1937
 
 
1938
          restore_time_zone(sql_file, delimiter);
 
1939
          restore_sql_mode(sql_file, delimiter);
 
1940
 
 
1941
          if (mysql_num_fields(event_res) >= 7)
 
1942
          {
 
1943
            restore_cs_variables(sql_file, delimiter);
 
1944
 
 
1945
            if (db_cl_altered)
 
1946
            {
 
1947
              if (restore_db_collation(sql_file, db_name_buff, delimiter,
 
1948
                                       db_cl_name))
 
1949
                DBUG_RETURN(1);
 
1950
            }
 
1951
          }
 
1952
        }
 
1953
      } /* end of event printing */
 
1954
      mysql_free_result(event_res);
 
1955
 
 
1956
    } /* end of list of events */
 
1957
    fprintf(sql_file, "DELIMITER ;\n");
 
1958
    fprintf(sql_file, "/*!50106 SET TIME_ZONE= @save_time_zone */ ;\n");
 
1959
 
 
1960
    if (switch_character_set_results(mysql, default_charset))
 
1961
      DBUG_RETURN(1);
 
1962
  }
 
1963
  mysql_free_result(event_list_res);
 
1964
 
 
1965
  if (lock_tables)
 
1966
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
 
1967
  DBUG_RETURN(0);
 
1968
}
 
1969
 
 
1970
 
 
1971
/*
 
1972
  Print hex value for blob data.
 
1973
 
 
1974
  SYNOPSIS
 
1975
    print_blob_as_hex()
 
1976
    output_file         - output file
 
1977
    str                 - string to print
 
1978
    len                 - its length
 
1979
 
 
1980
  DESCRIPTION
 
1981
    Print hex value for blob data.
 
1982
*/
 
1983
 
 
1984
static void print_blob_as_hex(FILE *output_file, const char *str, ulong len)
 
1985
{
 
1986
    /* sakaik got the idea to to provide blob's in hex notation. */
 
1987
    const char *ptr= str, *end= ptr + len;
 
1988
    for (; ptr < end ; ptr++)
 
1989
      fprintf(output_file, "%02X", *((uchar *)ptr));
 
1990
    check_io(output_file);
 
1991
}
 
1992
 
 
1993
/*
 
1994
  dump_routines_for_db
 
1995
  -- retrieves list of routines for a given db, and prints out
 
1996
  the CREATE PROCEDURE definition into the output (the dump).
 
1997
 
 
1998
  This function has logic to print the appropriate syntax depending on whether
 
1999
  this is a procedure or functions
 
2000
 
 
2001
  RETURN
 
2002
    0  Success
 
2003
    1  Error
 
2004
*/
 
2005
 
 
2006
static uint dump_routines_for_db(char *db)
 
2007
{
 
2008
  char       query_buff[QUERY_LENGTH];
 
2009
  const char *routine_type[]= {"FUNCTION", "PROCEDURE"};
 
2010
  char       db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
 
2011
  char       *routine_name;
 
2012
  int        i;
 
2013
  FILE       *sql_file= md_result_file;
 
2014
  MYSQL_RES  *routine_res, *routine_list_res;
 
2015
  MYSQL_ROW  row, routine_list_row;
 
2016
 
 
2017
  char       db_cl_name[MY_CS_NAME_SIZE];
 
2018
  int        db_cl_altered= FALSE;
 
2019
 
 
2020
  DBUG_ENTER("dump_routines_for_db");
 
2021
  DBUG_PRINT("enter", ("db: '%s'", db));
 
2022
 
 
2023
  mysql_real_escape_string(mysql, db_name_buff, db, strlen(db));
 
2024
 
 
2025
  /* nice comments */
 
2026
  if (opt_comments)
 
2027
    fprintf(sql_file, "\n--\n-- Dumping routines for database '%s'\n--\n", db);
 
2028
 
 
2029
  /*
 
2030
    not using "mysql_query_with_error_report" because we may have not
 
2031
    enough privileges to lock mysql.proc.
 
2032
  */
 
2033
  if (lock_tables)
 
2034
    mysql_query(mysql, "LOCK TABLES mysql.proc READ");
 
2035
 
 
2036
  /* Get database collation. */
 
2037
 
 
2038
  if (fetch_db_collation(db_name_buff, db_cl_name, sizeof (db_cl_name)))
 
2039
    DBUG_RETURN(1);
 
2040
 
 
2041
  if (switch_character_set_results(mysql, "binary"))
 
2042
    DBUG_RETURN(1);
 
2043
 
 
2044
  /* 0, retrieve and dump functions, 1, procedures */
 
2045
  for (i= 0; i <= 1; i++)
 
2046
  {
 
2047
    my_snprintf(query_buff, sizeof(query_buff),
 
2048
                "SHOW %s STATUS WHERE Db = '%s'",
 
2049
                routine_type[i], db_name_buff);
 
2050
 
 
2051
    if (mysql_query_with_error_report(mysql, &routine_list_res, query_buff))
 
2052
      DBUG_RETURN(1);
 
2053
 
 
2054
    if (mysql_num_rows(routine_list_res))
 
2055
    {
 
2056
 
 
2057
      while ((routine_list_row= mysql_fetch_row(routine_list_res)))
 
2058
      {
 
2059
        routine_name= quote_name(routine_list_row[1], name_buff, 0);
 
2060
        DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i],
 
2061
                            name_buff));
 
2062
        my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s",
 
2063
                    routine_type[i], routine_name);
 
2064
 
 
2065
        if (mysql_query_with_error_report(mysql, &routine_res, query_buff))
 
2066
          DBUG_RETURN(1);
 
2067
 
 
2068
        while ((row= mysql_fetch_row(routine_res)))
 
2069
        {
 
2070
          /*
 
2071
            if the user has EXECUTE privilege he see routine names, but NOT the
 
2072
            routine body of other routines that are not the creator of!
 
2073
          */
 
2074
          DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d",
 
2075
                             routine_name, row[2] ? row[2] : "(null)",
 
2076
                             row[2] ? (int) strlen(row[2]) : 0));
 
2077
          if (row[2] == NULL)
 
2078
          {
 
2079
            fprintf(sql_file, "\n-- insufficient privileges to %s\n", query_buff);
 
2080
            fprintf(sql_file, "-- does %s have permissions on mysql.proc?\n\n", current_user);
 
2081
            maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff);
 
2082
          }
 
2083
          else if (strlen(row[2]))
 
2084
          {
 
2085
            char *query_str;
 
2086
            if (opt_drop)
 
2087
              fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n",
 
2088
                      routine_type[i], routine_name);
 
2089
 
 
2090
            query_str= cover_definer_clause_in_sp(row[2], strlen(row[2]));
 
2091
 
 
2092
            if (mysql_num_fields(routine_res) >= 6)
 
2093
            {
 
2094
              if (switch_db_collation(sql_file, db_name_buff, ";",
 
2095
                                      db_cl_name, row[5], &db_cl_altered))
 
2096
              {
 
2097
                DBUG_RETURN(1);
 
2098
              }
 
2099
 
 
2100
              switch_cs_variables(sql_file, ";",
 
2101
                                  row[3],   /* character_set_client */
 
2102
                                  row[3],   /* character_set_results */
 
2103
                                  row[4]);  /* collation_connection */
 
2104
            }
 
2105
            else
 
2106
            {
 
2107
              /*
 
2108
                mysqldump is being run against the server, that does not
 
2109
                provide character set information in SHOW CREATE
 
2110
                statements.
 
2111
 
 
2112
                NOTE: the dump may be incorrect, since character set
 
2113
                information is required in order to restore stored
 
2114
                procedure/function properly.
 
2115
              */
 
2116
 
 
2117
              fprintf(sql_file,
 
2118
                      "--\n"
 
2119
                      "-- WARNING: old server version. "
 
2120
                        "The following dump may be incomplete.\n"
 
2121
                      "--\n");
 
2122
            }
 
2123
 
 
2124
 
 
2125
            switch_sql_mode(sql_file, ";", row[1]);
 
2126
 
 
2127
            fprintf(sql_file,
 
2128
                    "DELIMITER ;;\n"
 
2129
                    "/*!50003 %s */;;\n"
 
2130
                    "DELIMITER ;\n",
 
2131
                    (const char *) (query_str != NULL ? query_str : row[2]));
 
2132
 
 
2133
            restore_sql_mode(sql_file, ";");
 
2134
 
 
2135
            if (mysql_num_fields(routine_res) >= 6)
 
2136
            {
 
2137
              restore_cs_variables(sql_file, ";");
 
2138
 
 
2139
              if (db_cl_altered)
 
2140
              {
 
2141
                if (restore_db_collation(sql_file, db_name_buff, ";", db_cl_name))
 
2142
                  DBUG_RETURN(1);
 
2143
              }
 
2144
            }
 
2145
 
 
2146
            my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
 
2147
          }
 
2148
        } /* end of routine printing */
 
2149
        mysql_free_result(routine_res);
 
2150
 
 
2151
      } /* end of list of routines */
 
2152
    }
 
2153
    mysql_free_result(routine_list_res);
 
2154
  } /* end of for i (0 .. 1)  */
 
2155
 
 
2156
  if (switch_character_set_results(mysql, default_charset))
 
2157
    DBUG_RETURN(1);
 
2158
 
 
2159
  if (lock_tables)
 
2160
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
 
2161
  DBUG_RETURN(0);
 
2162
}
 
2163
 
 
2164
/*
 
2165
  get_table_structure -- retrievs database structure, prints out corresponding
 
2166
  CREATE statement and fills out insert_pat if the table is the type we will
 
2167
  be dumping.
 
2168
 
 
2169
  ARGS
 
2170
    table       - table name
 
2171
    db          - db name
 
2172
    table_type  - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
 
2173
    ignore_flag - what we must particularly ignore - see IGNORE_ defines above
 
2174
 
 
2175
  RETURN
 
2176
    number of fields in table, 0 if error
 
2177
*/
 
2178
 
 
2179
static uint get_table_structure(char *table, char *db, char *table_type,
 
2180
                                char *ignore_flag)
 
2181
{
 
2182
  my_bool    init=0, delayed, write_data, complete_insert;
 
2183
  my_ulonglong num_fields;
 
2184
  char       *result_table, *opt_quoted_table;
 
2185
  const char *insert_option;
 
2186
  char       name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
 
2187
  char       table_buff2[NAME_LEN*2+3], query_buff[QUERY_LENGTH];
 
2188
  FILE       *sql_file= md_result_file;
 
2189
  int        len;
 
2190
  MYSQL_RES  *result;
 
2191
  MYSQL_ROW  row;
 
2192
  DBUG_ENTER("get_table_structure");
 
2193
  DBUG_PRINT("enter", ("db: %s  table: %s", db, table));
 
2194
 
 
2195
  *ignore_flag= check_if_ignore_table(table, table_type);
 
2196
 
 
2197
  delayed= opt_delayed;
 
2198
  if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
 
2199
  {
 
2200
    delayed= 0;
 
2201
    verbose_msg("-- Warning: Unable to use delayed inserts for table '%s' "
 
2202
                "because it's of type %s\n", table, table_type);
 
2203
  }
 
2204
 
 
2205
  complete_insert= 0;
 
2206
  if ((write_data= !(*ignore_flag & IGNORE_DATA)))
 
2207
  {
 
2208
    complete_insert= opt_complete_insert;
 
2209
    if (!insert_pat_inited)
 
2210
    {
 
2211
      insert_pat_inited= 1;
 
2212
      init_dynamic_string_checked(&insert_pat, "", 1024, 1024);
 
2213
    }
 
2214
    else
 
2215
      dynstr_set_checked(&insert_pat, "");
 
2216
  }
 
2217
 
 
2218
  insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
 
2219
                  delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
 
2220
 
 
2221
  verbose_msg("-- Retrieving table structure for table %s...\n", table);
 
2222
 
 
2223
  len= my_snprintf(query_buff, sizeof(query_buff),
 
2224
                   "SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
 
2225
                   (opt_quoted || opt_keywords));
 
2226
 
 
2227
  result_table=     quote_name(table, table_buff, 1);
 
2228
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
2229
 
 
2230
  if (opt_order_by_primary)
 
2231
  {
 
2232
    my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
 
2233
    order_by= primary_key_fields(result_table);
 
2234
  }
 
2235
 
 
2236
  if (!opt_xml && !mysql_query_with_error_report(mysql, 0, query_buff))
 
2237
  {
 
2238
    /* using SHOW CREATE statement */
 
2239
    if (!opt_no_create_info)
 
2240
    {
 
2241
      /* Make an sql-file, if path was given iow. option -T was given */
 
2242
      char buff[20+FN_REFLEN];
 
2243
      MYSQL_FIELD *field;
 
2244
 
 
2245
      my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
 
2246
 
 
2247
      if (switch_character_set_results(mysql, "binary") ||
 
2248
          mysql_query_with_error_report(mysql, &result, buff) ||
 
2249
          switch_character_set_results(mysql, default_charset))
 
2250
        DBUG_RETURN(0);
 
2251
 
 
2252
      if (path)
 
2253
      {
 
2254
        if (!(sql_file= open_sql_file_for_table(table)))
 
2255
          DBUG_RETURN(0);
 
2256
 
 
2257
        write_header(sql_file, db);
 
2258
      }
 
2259
      if (!opt_xml && opt_comments)
 
2260
      {
 
2261
      if (strcmp (table_type, "VIEW") == 0)         /* view */
 
2262
        fprintf(sql_file, "\n--\n-- Temporary table structure for view %s\n--\n\n",
 
2263
                result_table);
 
2264
      else
 
2265
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
2266
                result_table);
 
2267
        check_io(sql_file);
 
2268
      }
 
2269
      if (opt_drop)
 
2270
      {
 
2271
      /*
 
2272
        Even if the "table" is a view, we do a DROP TABLE here.  The
 
2273
        view-specific code below fills in the DROP VIEW.
 
2274
       */
 
2275
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
 
2276
                opt_quoted_table);
 
2277
        check_io(sql_file);
 
2278
      }
 
2279
 
 
2280
      field= mysql_fetch_field_direct(result, 0);
 
2281
      if (strcmp(field->name, "View") == 0)
 
2282
      {
 
2283
        char *scv_buff= NULL;
 
2284
 
 
2285
        verbose_msg("-- It's a view, create dummy table for view\n");
 
2286
 
 
2287
        /* save "show create" statement for later */
 
2288
        if ((row= mysql_fetch_row(result)) && (scv_buff=row[1]))
 
2289
          scv_buff= my_strdup(scv_buff, MYF(0));
 
2290
 
 
2291
        mysql_free_result(result);
 
2292
 
 
2293
        /*
 
2294
          Create a table with the same name as the view and with columns of
 
2295
          the same name in order to satisfy views that depend on this view.
 
2296
          The table will be removed when the actual view is created.
 
2297
 
 
2298
          The properties of each column, aside from the data type, are not
 
2299
          preserved in this temporary table, because they are not necessary.
 
2300
 
 
2301
          This will not be necessary once we can determine dependencies
 
2302
          between views and can simply dump them in the appropriate order.
 
2303
        */
 
2304
        my_snprintf(query_buff, sizeof(query_buff),
 
2305
                    "SHOW FIELDS FROM %s", result_table);
 
2306
        if (switch_character_set_results(mysql, "binary") ||
 
2307
            mysql_query_with_error_report(mysql, &result, query_buff) ||
 
2308
            switch_character_set_results(mysql, default_charset))
 
2309
        {
 
2310
          /*
 
2311
            View references invalid or privileged table/col/fun (err 1356),
 
2312
            so we cannot create a stand-in table.  Be defensive and dump
 
2313
            a comment with the view's 'show create' statement. (Bug #17371)
 
2314
          */
 
2315
 
 
2316
          if (mysql_errno(mysql) == ER_VIEW_INVALID)
 
2317
            fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : "");
 
2318
 
 
2319
          my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
 
2320
 
 
2321
          DBUG_RETURN(0);
 
2322
        }
 
2323
        else
 
2324
          my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
 
2325
 
 
2326
        if (mysql_num_rows(result))
 
2327
        {
 
2328
          if (opt_drop)
 
2329
          {
 
2330
            /*
 
2331
              We have already dropped any table of the same name above, so
 
2332
              here we just drop the view.
 
2333
            */
 
2334
 
 
2335
            fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
 
2336
                    opt_quoted_table);
 
2337
            check_io(sql_file);
 
2338
          }
 
2339
 
 
2340
          fprintf(sql_file,
 
2341
                  "SET @saved_cs_client     = @@character_set_client;\n"
 
2342
                  "SET character_set_client = utf8;\n"
 
2343
                  "/*!50001 CREATE TABLE %s (\n",
 
2344
                  result_table);
 
2345
 
 
2346
          /*
 
2347
            Get first row, following loop will prepend comma - keeps from
 
2348
            having to know if the row being printed is last to determine if
 
2349
            there should be a _trailing_ comma.
 
2350
          */
 
2351
 
 
2352
          row= mysql_fetch_row(result);
 
2353
 
 
2354
          fprintf(sql_file, "  %s %s", quote_name(row[0], name_buff, 0),
 
2355
                  row[1]);
 
2356
 
 
2357
          while((row= mysql_fetch_row(result)))
 
2358
          {
 
2359
            /* col name, col type */
 
2360
            fprintf(sql_file, ",\n  %s %s",
 
2361
                    quote_name(row[0], name_buff, 0), row[1]);
 
2362
          }
 
2363
          fprintf(sql_file,
 
2364
                  "\n) */;\n"
 
2365
                  "SET character_set_client = @saved_cs_client;\n");
 
2366
 
 
2367
          check_io(sql_file);
 
2368
        }
 
2369
 
 
2370
        mysql_free_result(result);
 
2371
 
 
2372
        if (path)
 
2373
          my_fclose(sql_file, MYF(MY_WME));
 
2374
 
 
2375
        seen_views= 1;
 
2376
        DBUG_RETURN(0);
 
2377
      }
 
2378
 
 
2379
      row= mysql_fetch_row(result);
 
2380
 
 
2381
      fprintf(sql_file,
 
2382
              "SET @saved_cs_client     = @@character_set_client;\n"
 
2383
              "SET character_set_client = utf8;\n"
 
2384
              "%s;\n"
 
2385
              "SET character_set_client = @saved_cs_client;\n",
 
2386
              row[1]);
 
2387
 
 
2388
      check_io(sql_file);
 
2389
      mysql_free_result(result);
 
2390
    }
 
2391
    my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
2392
                result_table);
 
2393
    if (mysql_query_with_error_report(mysql, &result, query_buff))
 
2394
    {
 
2395
      if (path)
 
2396
        my_fclose(sql_file, MYF(MY_WME));
 
2397
      DBUG_RETURN(0);
 
2398
    }
 
2399
 
 
2400
    /*
 
2401
      If write_data is true, then we build up insert statements for
 
2402
      the table's data. Note: in subsequent lines of code, this test
 
2403
      will have to be performed each time we are appending to
 
2404
      insert_pat.
 
2405
    */
 
2406
    if (write_data)
 
2407
    {
 
2408
      if (opt_replace_into)
 
2409
        dynstr_append_checked(&insert_pat, "REPLACE ");
 
2410
      else
 
2411
        dynstr_append_checked(&insert_pat, "INSERT ");
 
2412
      dynstr_append_checked(&insert_pat, insert_option);
 
2413
      dynstr_append_checked(&insert_pat, "INTO ");
 
2414
      dynstr_append_checked(&insert_pat, opt_quoted_table);
 
2415
      if (complete_insert)
 
2416
      {
 
2417
        dynstr_append_checked(&insert_pat, " (");
 
2418
      }
 
2419
      else
 
2420
      {
 
2421
        dynstr_append_checked(&insert_pat, " VALUES ");
 
2422
        if (!extended_insert)
 
2423
          dynstr_append_checked(&insert_pat, "(");
 
2424
      }
 
2425
    }
 
2426
 
 
2427
    while ((row= mysql_fetch_row(result)))
 
2428
    {
 
2429
      if (complete_insert)
 
2430
      {
 
2431
        if (init)
 
2432
        {
 
2433
          dynstr_append_checked(&insert_pat, ", ");
 
2434
        }
 
2435
        init=1;
 
2436
        dynstr_append_checked(&insert_pat,
 
2437
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
2438
      }
 
2439
    }
 
2440
    num_fields= mysql_num_rows(result);
 
2441
    mysql_free_result(result);
 
2442
  }
 
2443
  else
 
2444
  {
 
2445
    verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
 
2446
                my_progname, mysql_error(mysql));
 
2447
 
 
2448
    my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
2449
                result_table);
 
2450
    if (mysql_query_with_error_report(mysql, &result, query_buff))
 
2451
      DBUG_RETURN(0);
 
2452
 
 
2453
    /* Make an sql-file, if path was given iow. option -T was given */
 
2454
    if (!opt_no_create_info)
 
2455
    {
 
2456
      if (path)
 
2457
      {
 
2458
        if (!(sql_file= open_sql_file_for_table(table)))
 
2459
          DBUG_RETURN(0);
 
2460
        write_header(sql_file, db);
 
2461
      }
 
2462
      if (!opt_xml && opt_comments)
 
2463
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
2464
                result_table);
 
2465
      if (opt_drop)
 
2466
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
 
2467
      if (!opt_xml)
 
2468
        fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
 
2469
      else
 
2470
        print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table, 
 
2471
                NullS);
 
2472
      check_io(sql_file);
 
2473
    }
 
2474
 
 
2475
    if (write_data)
 
2476
    {
 
2477
      if (opt_replace_into)
 
2478
        dynstr_append_checked(&insert_pat, "REPLACE ");
 
2479
      else
 
2480
        dynstr_append_checked(&insert_pat, "INSERT ");
 
2481
      dynstr_append_checked(&insert_pat, insert_option);
 
2482
      dynstr_append_checked(&insert_pat, "INTO ");
 
2483
      dynstr_append_checked(&insert_pat, result_table);
 
2484
      if (complete_insert)
 
2485
        dynstr_append_checked(&insert_pat, " (");
 
2486
      else
 
2487
      {
 
2488
        dynstr_append_checked(&insert_pat, " VALUES ");
 
2489
        if (!extended_insert)
 
2490
          dynstr_append_checked(&insert_pat, "(");
 
2491
      }
 
2492
    }
 
2493
 
 
2494
    while ((row= mysql_fetch_row(result)))
 
2495
    {
 
2496
      ulong *lengths= mysql_fetch_lengths(result);
 
2497
      if (init)
 
2498
      {
 
2499
        if (!opt_xml && !opt_no_create_info)
 
2500
        {
 
2501
          fputs(",\n",sql_file);
 
2502
          check_io(sql_file);
 
2503
        }
 
2504
        if (complete_insert)
 
2505
          dynstr_append_checked(&insert_pat, ", ");
 
2506
      }
 
2507
      init=1;
 
2508
      if (complete_insert)
 
2509
        dynstr_append_checked(&insert_pat,
 
2510
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
2511
      if (!opt_no_create_info)
 
2512
      {
 
2513
        if (opt_xml)
 
2514
        {
 
2515
          print_xml_row(sql_file, "field", result, &row);
 
2516
          continue;
 
2517
        }
 
2518
 
 
2519
        if (opt_keywords)
 
2520
          fprintf(sql_file, "  %s.%s %s", result_table,
 
2521
                  quote_name(row[SHOW_FIELDNAME],name_buff, 0),
 
2522
                  row[SHOW_TYPE]);
 
2523
        else
 
2524
          fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
 
2525
                                                  name_buff, 0),
 
2526
                  row[SHOW_TYPE]);
 
2527
        if (row[SHOW_DEFAULT])
 
2528
        {
 
2529
          fputs(" DEFAULT ", sql_file);
 
2530
          unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
 
2531
        }
 
2532
        if (!row[SHOW_NULL][0])
 
2533
          fputs(" NOT NULL", sql_file);
 
2534
        if (row[SHOW_EXTRA][0])
 
2535
          fprintf(sql_file, " %s",row[SHOW_EXTRA]);
 
2536
        check_io(sql_file);
 
2537
      }
 
2538
    }
 
2539
    num_fields= mysql_num_rows(result);
 
2540
    mysql_free_result(result);
 
2541
    if (!opt_no_create_info)
 
2542
    {
 
2543
      /* Make an sql-file, if path was given iow. option -T was given */
 
2544
      char buff[20+FN_REFLEN];
 
2545
      uint keynr,primary_key;
 
2546
      my_snprintf(buff, sizeof(buff), "show keys from %s", result_table);
 
2547
      if (mysql_query_with_error_report(mysql, &result, buff))
 
2548
      {
 
2549
        if (mysql_errno(mysql) == ER_WRONG_OBJECT)
 
2550
        {
 
2551
          /* it is VIEW */
 
2552
          fputs("\t\t<options Comment=\"view\" />\n", sql_file);
 
2553
          goto continue_xml;
 
2554
        }
 
2555
        fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
 
2556
                my_progname, result_table, mysql_error(mysql));
 
2557
        if (path)
 
2558
          my_fclose(sql_file, MYF(MY_WME));
 
2559
        DBUG_RETURN(0);
 
2560
      }
 
2561
 
 
2562
      /* Find first which key is primary key */
 
2563
      keynr=0;
 
2564
      primary_key=INT_MAX;
 
2565
      while ((row= mysql_fetch_row(result)))
 
2566
      {
 
2567
        if (atoi(row[3]) == 1)
 
2568
        {
 
2569
          keynr++;
 
2570
#ifdef FORCE_PRIMARY_KEY
 
2571
          if (atoi(row[1]) == 0 && primary_key == INT_MAX)
 
2572
            primary_key=keynr;
 
2573
#endif
 
2574
          if (!strcmp(row[2],"PRIMARY"))
 
2575
          {
 
2576
            primary_key=keynr;
 
2577
            break;
 
2578
          }
 
2579
        }
 
2580
      }
 
2581
      mysql_data_seek(result,0);
 
2582
      keynr=0;
 
2583
      while ((row= mysql_fetch_row(result)))
 
2584
      {
 
2585
        if (opt_xml)
 
2586
        {
 
2587
          print_xml_row(sql_file, "key", result, &row);
 
2588
          continue;
 
2589
        }
 
2590
 
 
2591
        if (atoi(row[3]) == 1)
 
2592
        {
 
2593
          if (keynr++)
 
2594
            putc(')', sql_file);
 
2595
          if (atoi(row[1]))       /* Test if duplicate key */
 
2596
            /* Duplicate allowed */
 
2597
            fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff,0));
 
2598
          else if (keynr == primary_key)
 
2599
            fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
 
2600
          else
 
2601
            fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff,
 
2602
                                                            0));
 
2603
        }
 
2604
        else
 
2605
          putc(',', sql_file);
 
2606
        fputs(quote_name(row[4], name_buff, 0), sql_file);
 
2607
        if (row[7])
 
2608
          fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
 
2609
        check_io(sql_file);
 
2610
      }
 
2611
      mysql_free_result(result);
 
2612
      if (!opt_xml)
 
2613
      {
 
2614
        if (keynr)
 
2615
          putc(')', sql_file);
 
2616
        fputs("\n)",sql_file);
 
2617
        check_io(sql_file);
 
2618
      }
 
2619
 
 
2620
      /* Get MySQL specific create options */
 
2621
      if (create_options)
 
2622
      {
 
2623
        char show_name_buff[NAME_LEN*2+2+24];
 
2624
 
 
2625
        /* Check memory for quote_for_like() */
 
2626
        my_snprintf(buff, sizeof(buff), "show table status like %s",
 
2627
                    quote_for_like(table, show_name_buff));
 
2628
 
 
2629
        if (mysql_query_with_error_report(mysql, &result, buff))
 
2630
        {
 
2631
          if (mysql_errno(mysql) != ER_PARSE_ERROR)
 
2632
          {                                     /* If old MySQL version */
 
2633
            verbose_msg("-- Warning: Couldn't get status information for " \
 
2634
                        "table %s (%s)\n", result_table,mysql_error(mysql));
 
2635
          }
 
2636
        }
 
2637
        else if (!(row= mysql_fetch_row(result)))
 
2638
        {
 
2639
          fprintf(stderr,
 
2640
                  "Error: Couldn't read status information for table %s (%s)\n",
 
2641
                  result_table,mysql_error(mysql));
 
2642
        }
 
2643
        else
 
2644
        {
 
2645
          if (opt_xml)
 
2646
            print_xml_row(sql_file, "options", result, &row);
 
2647
          else
 
2648
          {
 
2649
            fputs("/*!",sql_file);
 
2650
            print_value(sql_file,result,row,"engine=","Engine",0);
 
2651
            print_value(sql_file,result,row,"","Create_options",0);
 
2652
            print_value(sql_file,result,row,"comment=","Comment",1);
 
2653
            fputs(" */",sql_file);
 
2654
            check_io(sql_file);
 
2655
          }
 
2656
        }
 
2657
        mysql_free_result(result);              /* Is always safe to free */
 
2658
      }
 
2659
continue_xml:
 
2660
      if (!opt_xml)
 
2661
        fputs(";\n", sql_file);
 
2662
      else
 
2663
        fputs("\t</table_structure>\n", sql_file);
 
2664
      check_io(sql_file);
 
2665
    }
 
2666
  }
 
2667
  if (complete_insert)
 
2668
  {
 
2669
    dynstr_append_checked(&insert_pat, ") VALUES ");
 
2670
    if (!extended_insert)
 
2671
      dynstr_append_checked(&insert_pat, "(");
 
2672
  }
 
2673
  if (sql_file != md_result_file)
 
2674
  {
 
2675
    fputs("\n", sql_file);
 
2676
    write_footer(sql_file);
 
2677
    my_fclose(sql_file, MYF(MY_WME));
 
2678
  }
 
2679
  DBUG_RETURN((uint) num_fields);
 
2680
} /* get_table_structure */
 
2681
 
 
2682
static void add_load_option(DYNAMIC_STRING *str, const char *option,
 
2683
                             const char *option_value)
 
2684
{
 
2685
  if (!option_value)
 
2686
  {
 
2687
    /* Null value means we don't add this option. */
 
2688
    return;
 
2689
  }
 
2690
 
 
2691
  dynstr_append_checked(str, option);
 
2692
  
 
2693
  if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
 
2694
  {
 
2695
    /* It's a hex constant, don't escape */
 
2696
    dynstr_append_checked(str, option_value);
 
2697
  }
 
2698
  else
 
2699
  {
 
2700
    /* char constant; escape */
 
2701
    field_escape(str, option_value);
 
2702
  }
 
2703
}
 
2704
 
 
2705
 
 
2706
/*
 
2707
  Allow the user to specify field terminator strings like:
 
2708
  "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
 
2709
  This is done by doubling ' and add a end -\ if needed to avoid
 
2710
  syntax errors from the SQL parser.
 
2711
*/
 
2712
 
 
2713
static void field_escape(DYNAMIC_STRING* in, const char *from)
 
2714
{
 
2715
  uint end_backslashes= 0; 
 
2716
 
 
2717
  dynstr_append_checked(in, "'");
 
2718
 
 
2719
  while (*from)
 
2720
  {
 
2721
    dynstr_append_mem_checked(in, from, 1);
 
2722
 
 
2723
    if (*from == '\\')
 
2724
      end_backslashes^=1;    /* find odd number of backslashes */
 
2725
    else
 
2726
    {
 
2727
      if (*from == '\'' && !end_backslashes)
 
2728
      {
 
2729
        /* We want a duplicate of "'" for MySQL */
 
2730
        dynstr_append_checked(in, "\'");
 
2731
      }
 
2732
      end_backslashes=0;
 
2733
    }
 
2734
    from++;
 
2735
  }
 
2736
  /* Add missing backslashes if user has specified odd number of backs.*/
 
2737
  if (end_backslashes)
 
2738
    dynstr_append_checked(in, "\\");
 
2739
  
 
2740
  dynstr_append_checked(in, "'");
 
2741
}
 
2742
 
 
2743
 
 
2744
 
 
2745
static char *alloc_query_str(ulong size)
 
2746
{
 
2747
  char *query;
 
2748
 
 
2749
  if (!(query= (char*) my_malloc(size, MYF(MY_WME))))
 
2750
    die(EX_MYSQLERR, "Couldn't allocate a query string.");
 
2751
 
 
2752
  return query;
 
2753
}
 
2754
 
 
2755
 
 
2756
/*
 
2757
 
 
2758
 SYNOPSIS
 
2759
  dump_table()
 
2760
 
 
2761
  dump_table saves database contents as a series of INSERT statements.
 
2762
 
 
2763
  ARGS
 
2764
   table - table name
 
2765
   db    - db name
 
2766
 
 
2767
   RETURNS
 
2768
    void
 
2769
*/
 
2770
 
 
2771
 
 
2772
static void dump_table(char *table, char *db)
 
2773
{
 
2774
  char ignore_flag;
 
2775
  char buf[200], table_buff[NAME_LEN+3];
 
2776
  DYNAMIC_STRING query_string;
 
2777
  char table_type[NAME_LEN];
 
2778
  char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
 
2779
  int error= 0;
 
2780
  ulong         rownr, row_break, total_length, init_length;
 
2781
  uint num_fields;
 
2782
  MYSQL_RES     *res;
 
2783
  MYSQL_FIELD   *field;
 
2784
  MYSQL_ROW     row;
 
2785
  DBUG_ENTER("dump_table");
 
2786
 
 
2787
  /*
 
2788
    Make sure you get the create table info before the following check for
 
2789
    --no-data flag below. Otherwise, the create table info won't be printed.
 
2790
  */
 
2791
  num_fields= get_table_structure(table, db, table_type, &ignore_flag);
 
2792
 
 
2793
  /*
 
2794
    The "table" could be a view.  If so, we don't do anything here.
 
2795
  */
 
2796
  if (strcmp(table_type, "VIEW") == 0)
 
2797
    DBUG_VOID_RETURN;
 
2798
 
 
2799
  /* Check --no-data flag */
 
2800
  if (opt_no_data)
 
2801
  {
 
2802
    verbose_msg("-- Skipping dump data for table '%s', --no-data was used\n",
 
2803
                table);
 
2804
    DBUG_VOID_RETURN;
 
2805
  }
 
2806
 
 
2807
  DBUG_PRINT("info",
 
2808
             ("ignore_flag: %x  num_fields: %d", (int) ignore_flag,
 
2809
              num_fields));
 
2810
  /*
 
2811
    If the table type is a merge table or any type that has to be
 
2812
     _completely_ ignored and no data dumped
 
2813
  */
 
2814
  if (ignore_flag & IGNORE_DATA)
 
2815
  {
 
2816
    verbose_msg("-- Warning: Skipping data for table '%s' because " \
 
2817
                "it's of type %s\n", table, table_type);
 
2818
    DBUG_VOID_RETURN;
 
2819
  }
 
2820
  /* Check that there are any fields in the table */
 
2821
  if (num_fields == 0)
 
2822
  {
 
2823
    verbose_msg("-- Skipping dump data for table '%s', it has no fields\n",
 
2824
                table);
 
2825
    DBUG_VOID_RETURN;
 
2826
  }
 
2827
 
 
2828
  /*
 
2829
     Check --skip-events flag: it is not enough to skip creation of events
 
2830
     discarding SHOW CREATE EVENT statements generation. The myslq.event
 
2831
     table data should be skipped too.
 
2832
  */
 
2833
  if (!opt_events && !my_strcasecmp(&my_charset_latin1, db, "mysql") &&
 
2834
      !my_strcasecmp(&my_charset_latin1, table, "event"))
 
2835
  {
 
2836
    verbose_msg("-- Skipping data table mysql.event, --skip-events was used\n");
 
2837
    DBUG_VOID_RETURN;
 
2838
  }
 
2839
 
 
2840
  result_table= quote_name(table,table_buff, 1);
 
2841
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
2842
 
 
2843
  verbose_msg("-- Sending SELECT query...\n");
 
2844
 
 
2845
  init_dynamic_string_checked(&query_string, "", 1024, 1024);
 
2846
 
 
2847
  if (path)
 
2848
  {
 
2849
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
2850
 
 
2851
    /*
 
2852
      Convert the path to native os format
 
2853
      and resolve to the full filepath.
 
2854
    */
 
2855
    convert_dirname(tmp_path,path,NullS);    
 
2856
    my_load_path(tmp_path, tmp_path, NULL);
 
2857
    fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
 
2858
 
 
2859
    /* Must delete the file that 'INTO OUTFILE' will write to */
 
2860
    my_delete(filename, MYF(0));
 
2861
 
 
2862
    /* convert to a unix path name to stick into the query */
 
2863
    to_unix_path(filename);
 
2864
 
 
2865
    /* now build the query string */
 
2866
 
 
2867
    dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '");
 
2868
    dynstr_append_checked(&query_string, filename);
 
2869
    dynstr_append_checked(&query_string, "'");
 
2870
 
 
2871
    if (fields_terminated || enclosed || opt_enclosed || escaped)
 
2872
      dynstr_append_checked(&query_string, " FIELDS");
 
2873
    
 
2874
    add_load_option(&query_string, " TERMINATED BY ", fields_terminated);
 
2875
    add_load_option(&query_string, " ENCLOSED BY ", enclosed);
 
2876
    add_load_option(&query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
 
2877
    add_load_option(&query_string, " ESCAPED BY ", escaped);
 
2878
    add_load_option(&query_string, " LINES TERMINATED BY ", lines_terminated);
 
2879
 
 
2880
    dynstr_append_checked(&query_string, " FROM ");
 
2881
    dynstr_append_checked(&query_string, result_table);
 
2882
 
 
2883
    if (where)
 
2884
    {
 
2885
      dynstr_append_checked(&query_string, " WHERE ");
 
2886
      dynstr_append_checked(&query_string, where);
 
2887
    }
 
2888
 
 
2889
    if (order_by)
 
2890
    {
 
2891
      dynstr_append_checked(&query_string, " ORDER BY ");
 
2892
      dynstr_append_checked(&query_string, order_by);
 
2893
    }
 
2894
 
 
2895
    if (mysql_real_query(mysql, query_string.str, query_string.length))
 
2896
    {
 
2897
      DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
 
2898
      dynstr_free(&query_string);
 
2899
      DBUG_VOID_RETURN;
 
2900
    }
 
2901
  }
 
2902
  else
 
2903
  {
 
2904
    if (!opt_xml && opt_comments)
 
2905
    {
 
2906
      fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
 
2907
              result_table);
 
2908
      check_io(md_result_file);
 
2909
    }
 
2910
    
 
2911
    dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM ");
 
2912
    dynstr_append_checked(&query_string, result_table);
 
2913
 
 
2914
    if (where)
 
2915
    {
 
2916
      if (!opt_xml && opt_comments)
 
2917
      {
 
2918
        fprintf(md_result_file, "-- WHERE:  %s\n", where);
 
2919
        check_io(md_result_file);
 
2920
      }
 
2921
      
 
2922
      dynstr_append_checked(&query_string, " WHERE ");
 
2923
      dynstr_append_checked(&query_string, where);
 
2924
    }
 
2925
    if (order_by)
 
2926
    {
 
2927
      if (!opt_xml && opt_comments)
 
2928
      {
 
2929
        fprintf(md_result_file, "-- ORDER BY:  %s\n", order_by);
 
2930
        check_io(md_result_file);
 
2931
      }
 
2932
      dynstr_append_checked(&query_string, " ORDER BY ");
 
2933
      dynstr_append_checked(&query_string, order_by);
 
2934
    }
 
2935
 
 
2936
    if (!opt_xml && !opt_compact)
 
2937
    {
 
2938
      fputs("\n", md_result_file);
 
2939
      check_io(md_result_file);
 
2940
    }
 
2941
    if (mysql_query_with_error_report(mysql, 0, query_string.str))
 
2942
    {
 
2943
      DB_error(mysql, "when retrieving data from server");
 
2944
      goto err;
 
2945
    }
 
2946
    if (quick)
 
2947
      res=mysql_use_result(mysql);
 
2948
    else
 
2949
      res=mysql_store_result(mysql);
 
2950
    if (!res)
 
2951
    {
 
2952
      DB_error(mysql, "when retrieving data from server");
 
2953
      goto err;
 
2954
    }
 
2955
 
 
2956
    verbose_msg("-- Retrieving rows...\n");
 
2957
    if (mysql_num_fields(res) != num_fields)
 
2958
    {
 
2959
      fprintf(stderr,"%s: Error in field count for table: %s !  Aborting.\n",
 
2960
              my_progname, result_table);
 
2961
      error= EX_CONSCHECK;
 
2962
      goto err;
 
2963
    }
 
2964
 
 
2965
    if (opt_lock)
 
2966
    {
 
2967
      fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
 
2968
      check_io(md_result_file);
 
2969
    }
 
2970
    /* Moved disable keys to after lock per bug 15977 */
 
2971
    if (opt_disable_keys)
 
2972
    {
 
2973
      fprintf(md_result_file, "/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
 
2974
              opt_quoted_table);
 
2975
      check_io(md_result_file);
 
2976
    }
 
2977
 
 
2978
    total_length= opt_net_buffer_length;                /* Force row break */
 
2979
    row_break=0;
 
2980
    rownr=0;
 
2981
    init_length=(uint) insert_pat.length+4;
 
2982
    if (opt_xml)
 
2983
      print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
 
2984
              NullS);
 
2985
    if (opt_autocommit)
 
2986
    {
 
2987
      fprintf(md_result_file, "set autocommit=0;\n");
 
2988
      check_io(md_result_file);
 
2989
    }
 
2990
 
 
2991
    while ((row= mysql_fetch_row(res)))
 
2992
    {
 
2993
      uint i;
 
2994
      ulong *lengths= mysql_fetch_lengths(res);
 
2995
      rownr++;
 
2996
      if (!extended_insert && !opt_xml)
 
2997
      {
 
2998
        fputs(insert_pat.str,md_result_file);
 
2999
        check_io(md_result_file);
 
3000
      }
 
3001
      mysql_field_seek(res,0);
 
3002
 
 
3003
      if (opt_xml)
 
3004
      {
 
3005
        fputs("\t<row>\n", md_result_file);
 
3006
        check_io(md_result_file);
 
3007
      }
 
3008
 
 
3009
      for (i= 0; i < mysql_num_fields(res); i++)
 
3010
      {
 
3011
        int is_blob;
 
3012
        ulong length= lengths[i];
 
3013
 
 
3014
        if (!(field= mysql_fetch_field(res)))
 
3015
          die(EX_CONSCHECK,
 
3016
                      "Not enough fields from table %s! Aborting.\n",
 
3017
                      result_table);
 
3018
 
 
3019
        /*
 
3020
           63 is my_charset_bin. If charsetnr is not 63,
 
3021
           we have not a BLOB but a TEXT column.
 
3022
           we'll dump in hex only BLOB columns.
 
3023
        */
 
3024
        is_blob= (opt_hex_blob && field->charsetnr == 63 &&
 
3025
                  (field->type == MYSQL_TYPE_BIT ||
 
3026
                   field->type == MYSQL_TYPE_STRING ||
 
3027
                   field->type == MYSQL_TYPE_VAR_STRING ||
 
3028
                   field->type == MYSQL_TYPE_VARCHAR ||
 
3029
                   field->type == MYSQL_TYPE_BLOB ||
 
3030
                   field->type == MYSQL_TYPE_LONG_BLOB ||
 
3031
                   field->type == MYSQL_TYPE_MEDIUM_BLOB ||
 
3032
                   field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0;
 
3033
        if (extended_insert && !opt_xml)
 
3034
        {
 
3035
          if (i == 0)
 
3036
            dynstr_set_checked(&extended_row,"(");
 
3037
          else
 
3038
            dynstr_append_checked(&extended_row,",");
 
3039
 
 
3040
          if (row[i])
 
3041
          {
 
3042
            if (length)
 
3043
            {
 
3044
              if (!IS_NUM_FIELD(field))
 
3045
              {
 
3046
                /*
 
3047
                  "length * 2 + 2" is OK for both HEX and non-HEX modes:
 
3048
                  - In HEX mode we need exactly 2 bytes per character
 
3049
                  plus 2 bytes for '0x' prefix.
 
3050
                  - In non-HEX mode we need up to 2 bytes per character,
 
3051
                  plus 2 bytes for leading and trailing '\'' characters.
 
3052
                  Also we need to reserve 1 byte for terminating '\0'.
 
3053
                */
 
3054
                dynstr_realloc_checked(&extended_row,length * 2 + 2 + 1);
 
3055
                if (opt_hex_blob && is_blob)
 
3056
                {
 
3057
                  dynstr_append_checked(&extended_row, "0x");
 
3058
                  extended_row.length+= mysql_hex_string(extended_row.str +
 
3059
                                                         extended_row.length,
 
3060
                                                         row[i], length);
 
3061
                  DBUG_ASSERT(extended_row.length+1 <= extended_row.max_length);
 
3062
                  /* mysql_hex_string() already terminated string by '\0' */
 
3063
                  DBUG_ASSERT(extended_row.str[extended_row.length] == '\0');
 
3064
                }
 
3065
                else
 
3066
                {
 
3067
                  dynstr_append_checked(&extended_row,"'");
 
3068
                  extended_row.length +=
 
3069
                  mysql_real_escape_string(&mysql_connection,
 
3070
                                           &extended_row.str[extended_row.length],
 
3071
                                           row[i],length);
 
3072
                  extended_row.str[extended_row.length]='\0';
 
3073
                  dynstr_append_checked(&extended_row,"'");
 
3074
                }
 
3075
              }
 
3076
              else
 
3077
              {
 
3078
                /* change any strings ("inf", "-inf", "nan") into NULL */
 
3079
                char *ptr= row[i];
 
3080
                if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
 
3081
                    my_isalpha(charset_info, ptr[1])))
 
3082
                  dynstr_append_checked(&extended_row, "NULL");
 
3083
                else
 
3084
                {
 
3085
                  if (field->type == MYSQL_TYPE_DECIMAL)
 
3086
                  {
 
3087
                    /* add " signs around */
 
3088
                    dynstr_append_checked(&extended_row, "'");
 
3089
                    dynstr_append_checked(&extended_row, ptr);
 
3090
                    dynstr_append_checked(&extended_row, "'");
 
3091
                  }
 
3092
                  else
 
3093
                    dynstr_append_checked(&extended_row, ptr);
 
3094
                }
 
3095
              }
 
3096
            }
 
3097
            else
 
3098
              dynstr_append_checked(&extended_row,"''");
 
3099
          }
 
3100
          else
 
3101
            dynstr_append_checked(&extended_row,"NULL");
 
3102
        }
 
3103
        else
 
3104
        {
 
3105
          if (i && !opt_xml)
 
3106
          {
 
3107
            fputc(',', md_result_file);
 
3108
            check_io(md_result_file);
 
3109
          }
 
3110
          if (row[i])
 
3111
          {
 
3112
            if (!IS_NUM_FIELD(field))
 
3113
            {
 
3114
              if (opt_xml)
 
3115
              {
 
3116
                if (opt_hex_blob && is_blob && length)
 
3117
                {
 
3118
                  /* Define xsi:type="xs:hexBinary" for hex encoded data */
 
3119
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
3120
                                field->name, "xsi:type=", "xs:hexBinary", NullS);
 
3121
                  print_blob_as_hex(md_result_file, row[i], length);
 
3122
                }
 
3123
                else
 
3124
                {
 
3125
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=", 
 
3126
                                field->name, NullS);
 
3127
                  print_quoted_xml(md_result_file, row[i], length);
 
3128
                }
 
3129
                fputs("</field>\n", md_result_file);
 
3130
              }
 
3131
              else if (opt_hex_blob && is_blob && length)
 
3132
              {
 
3133
                fputs("0x", md_result_file);
 
3134
                print_blob_as_hex(md_result_file, row[i], length);
 
3135
              }
 
3136
              else
 
3137
                unescape(md_result_file, row[i], length);
 
3138
            }
 
3139
            else
 
3140
            {
 
3141
              /* change any strings ("inf", "-inf", "nan") into NULL */
 
3142
              char *ptr= row[i];
 
3143
              if (opt_xml)
 
3144
              {
 
3145
                print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
3146
                        field->name, NullS);
 
3147
                fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
 
3148
                      md_result_file);
 
3149
                fputs("</field>\n", md_result_file);
 
3150
              }
 
3151
              else if (my_isalpha(charset_info, *ptr) ||
 
3152
                       (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
 
3153
                fputs("NULL", md_result_file);
 
3154
              else if (field->type == MYSQL_TYPE_DECIMAL)
 
3155
              {
 
3156
                /* add " signs around */
 
3157
                fputc('\'', md_result_file);
 
3158
                fputs(ptr, md_result_file);
 
3159
                fputc('\'', md_result_file);
 
3160
              }
 
3161
              else
 
3162
                fputs(ptr, md_result_file);
 
3163
            }
 
3164
          }
 
3165
          else
 
3166
          {
 
3167
            /* The field value is NULL */
 
3168
            if (!opt_xml)
 
3169
              fputs("NULL", md_result_file);
 
3170
            else
 
3171
              print_xml_null_tag(md_result_file, "\t\t", "field name=",
 
3172
                                 field->name, "\n");
 
3173
          }
 
3174
          check_io(md_result_file);
 
3175
        }
 
3176
      }
 
3177
 
 
3178
      if (opt_xml)
 
3179
      {
 
3180
        fputs("\t</row>\n", md_result_file);
 
3181
        check_io(md_result_file);
 
3182
      }
 
3183
 
 
3184
      if (extended_insert)
 
3185
      {
 
3186
        ulong row_length;
 
3187
        dynstr_append_checked(&extended_row,")");
 
3188
        row_length= 2 + extended_row.length;
 
3189
        if (total_length + row_length < opt_net_buffer_length)
 
3190
        {
 
3191
          total_length+= row_length;
 
3192
          fputc(',',md_result_file);            /* Always row break */
 
3193
          fputs(extended_row.str,md_result_file);
 
3194
        }
 
3195
        else
 
3196
        {
 
3197
          if (row_break)
 
3198
            fputs(";\n", md_result_file);
 
3199
          row_break=1;                          /* This is first row */
 
3200
 
 
3201
          fputs(insert_pat.str,md_result_file);
 
3202
          fputs(extended_row.str,md_result_file);
 
3203
          total_length= row_length+init_length;
 
3204
        }
 
3205
        check_io(md_result_file);
 
3206
      }
 
3207
      else if (!opt_xml)
 
3208
      {
 
3209
        fputs(");\n", md_result_file);
 
3210
        check_io(md_result_file);
 
3211
      }
 
3212
    }
 
3213
 
 
3214
    /* XML - close table tag and supress regular output */
 
3215
    if (opt_xml)
 
3216
        fputs("\t</table_data>\n", md_result_file);
 
3217
    else if (extended_insert && row_break)
 
3218
      fputs(";\n", md_result_file);             /* If not empty table */
 
3219
    fflush(md_result_file);
 
3220
    check_io(md_result_file);
 
3221
    if (mysql_errno(mysql))
 
3222
    {
 
3223
      my_snprintf(buf, sizeof(buf),
 
3224
                  "%s: Error %d: %s when dumping table %s at row: %ld\n",
 
3225
                  my_progname,
 
3226
                  mysql_errno(mysql),
 
3227
                  mysql_error(mysql),
 
3228
                  result_table,
 
3229
                  rownr);
 
3230
      fputs(buf,stderr);
 
3231
      error= EX_CONSCHECK;
 
3232
      goto err;
 
3233
    }
 
3234
 
 
3235
    /* Moved enable keys to before unlock per bug 15977 */
 
3236
    if (opt_disable_keys)
 
3237
    {
 
3238
      fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
 
3239
              opt_quoted_table);
 
3240
      check_io(md_result_file);
 
3241
    }
 
3242
    if (opt_lock)
 
3243
    {
 
3244
      fputs("UNLOCK TABLES;\n", md_result_file);
 
3245
      check_io(md_result_file);
 
3246
    }
 
3247
    if (opt_autocommit)
 
3248
    {
 
3249
      fprintf(md_result_file, "commit;\n");
 
3250
      check_io(md_result_file);
 
3251
    }
 
3252
    mysql_free_result(res);
 
3253
  }
 
3254
  dynstr_free(&query_string);
 
3255
  DBUG_VOID_RETURN;
 
3256
 
 
3257
err:
 
3258
  dynstr_free(&query_string);
 
3259
  maybe_exit(error);
 
3260
  DBUG_VOID_RETURN;
 
3261
} /* dump_table */
 
3262
 
 
3263
 
 
3264
static char *getTableName(int reset)
 
3265
{
 
3266
  static MYSQL_RES *res= NULL;
 
3267
  MYSQL_ROW    row;
 
3268
 
 
3269
  if (!res)
 
3270
  {
 
3271
    if (!(res= mysql_list_tables(mysql,NullS)))
 
3272
      return(NULL);
 
3273
  }
 
3274
  if ((row= mysql_fetch_row(res)))
 
3275
    return((char*) row[0]);
 
3276
 
 
3277
  if (reset)
 
3278
    mysql_data_seek(res,0);      /* We want to read again */
 
3279
  else
 
3280
  {
 
3281
    mysql_free_result(res);
 
3282
    res= NULL;
 
3283
  }
 
3284
  return(NULL);
 
3285
} /* getTableName */
 
3286
 
 
3287
 
 
3288
/*
 
3289
  dump all logfile groups and tablespaces
 
3290
*/
 
3291
 
 
3292
static int dump_all_tablespaces()
 
3293
{
 
3294
  return dump_tablespaces(NULL);
 
3295
}
 
3296
 
 
3297
static int dump_tablespaces_for_tables(char *db, char **table_names, int tables)
 
3298
{
 
3299
  DYNAMIC_STRING where;
 
3300
  int r;
 
3301
  int i;
 
3302
  char name_buff[NAME_LEN*2+3];
 
3303
 
 
3304
  mysql_real_escape_string(mysql, name_buff, db, strlen(db));
 
3305
 
 
3306
  init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN ("
 
3307
                      "SELECT DISTINCT TABLESPACE_NAME FROM"
 
3308
                      " INFORMATION_SCHEMA.PARTITIONS"
 
3309
                      " WHERE"
 
3310
                      " TABLE_SCHEMA='", 256, 1024);
 
3311
  dynstr_append_checked(&where, name_buff);
 
3312
  dynstr_append_checked(&where, "' AND TABLE_NAME IN (");
 
3313
 
 
3314
  for (i=0 ; i<tables ; i++)
 
3315
  {
 
3316
    mysql_real_escape_string(mysql, name_buff,
 
3317
                             table_names[i], strlen(table_names[i]));
 
3318
 
 
3319
    dynstr_append_checked(&where, "'");
 
3320
    dynstr_append_checked(&where, name_buff);
 
3321
    dynstr_append_checked(&where, "',");
 
3322
  }
 
3323
  dynstr_trunc(&where, 1);
 
3324
  dynstr_append_checked(&where,"))");
 
3325
 
 
3326
  DBUG_PRINT("info",("Dump TS for Tables where: %s",where.str));
 
3327
  r= dump_tablespaces(where.str);
 
3328
  dynstr_free(&where);
 
3329
  return r;
 
3330
}
 
3331
 
 
3332
static int dump_tablespaces_for_databases(char** databases)
 
3333
{
 
3334
  DYNAMIC_STRING where;
 
3335
  int r;
 
3336
  int i;
 
3337
 
 
3338
  init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN ("
 
3339
                      "SELECT DISTINCT TABLESPACE_NAME FROM"
 
3340
                      " INFORMATION_SCHEMA.PARTITIONS"
 
3341
                      " WHERE"
 
3342
                      " TABLE_SCHEMA IN (", 256, 1024);
 
3343
 
 
3344
  for (i=0 ; databases[i]!=NULL ; i++)
 
3345
  {
 
3346
    char db_name_buff[NAME_LEN*2+3];
 
3347
    mysql_real_escape_string(mysql, db_name_buff,
 
3348
                             databases[i], strlen(databases[i]));
 
3349
    dynstr_append_checked(&where, "'");
 
3350
    dynstr_append_checked(&where, db_name_buff);
 
3351
    dynstr_append_checked(&where, "',");
 
3352
  }
 
3353
  dynstr_trunc(&where, 1);
 
3354
  dynstr_append_checked(&where,"))");
 
3355
 
 
3356
  DBUG_PRINT("info",("Dump TS for DBs where: %s",where.str));
 
3357
  r= dump_tablespaces(where.str);
 
3358
  dynstr_free(&where);
 
3359
  return r;
 
3360
}
 
3361
 
 
3362
static int dump_tablespaces(char* ts_where)
 
3363
{
 
3364
  MYSQL_ROW row;
 
3365
  MYSQL_RES *tableres;
 
3366
  char buf[FN_REFLEN];
 
3367
  DYNAMIC_STRING sqlbuf;
 
3368
  int first= 0;
 
3369
  /*
 
3370
    The following are used for parsing the EXTRA field
 
3371
  */
 
3372
  char extra_format[]= "UNDO_BUFFER_SIZE=";
 
3373
  char *ubs;
 
3374
  char *endsemi;
 
3375
  DBUG_ENTER("dump_tablespaces");
 
3376
 
 
3377
  init_dynamic_string_checked(&sqlbuf,
 
3378
                      "SELECT LOGFILE_GROUP_NAME,"
 
3379
                      " FILE_NAME,"
 
3380
                      " TOTAL_EXTENTS,"
 
3381
                      " INITIAL_SIZE,"
 
3382
                      " ENGINE,"
 
3383
                      " EXTRA"
 
3384
                      " FROM INFORMATION_SCHEMA.FILES"
 
3385
                      " WHERE FILE_TYPE = 'UNDO LOG'"
 
3386
                      " AND FILE_NAME IS NOT NULL",
 
3387
                      256, 1024);
 
3388
  if(ts_where)
 
3389
  {
 
3390
    dynstr_append_checked(&sqlbuf,
 
3391
                  " AND LOGFILE_GROUP_NAME IN ("
 
3392
                  "SELECT DISTINCT LOGFILE_GROUP_NAME"
 
3393
                  " FROM INFORMATION_SCHEMA.FILES"
 
3394
                  " WHERE FILE_TYPE = 'DATAFILE'"
 
3395
                  );
 
3396
    dynstr_append_checked(&sqlbuf, ts_where);
 
3397
    dynstr_append_checked(&sqlbuf, ")");
 
3398
  }
 
3399
  dynstr_append_checked(&sqlbuf,
 
3400
                " GROUP BY LOGFILE_GROUP_NAME, FILE_NAME"
 
3401
                ", ENGINE"
 
3402
                " ORDER BY LOGFILE_GROUP_NAME");
 
3403
 
 
3404
  if (mysql_query(mysql, sqlbuf.str) ||
 
3405
      !(tableres = mysql_store_result(mysql)))
 
3406
  {
 
3407
    dynstr_free(&sqlbuf);
 
3408
    if (mysql_errno(mysql) == ER_BAD_TABLE_ERROR ||
 
3409
        mysql_errno(mysql) == ER_BAD_DB_ERROR ||
 
3410
        mysql_errno(mysql) == ER_UNKNOWN_TABLE)
 
3411
    {
 
3412
      fprintf(md_result_file,
 
3413
              "\n--\n-- Not dumping tablespaces as no INFORMATION_SCHEMA.FILES"
 
3414
              " table on this server\n--\n");
 
3415
      check_io(md_result_file);
 
3416
      DBUG_RETURN(0);
 
3417
    }
 
3418
 
 
3419
    my_printf_error(0, "Error: '%s' when trying to dump tablespaces",
 
3420
                    MYF(0), mysql_error(mysql));
 
3421
    DBUG_RETURN(1);
 
3422
  }
 
3423
 
 
3424
  buf[0]= 0;
 
3425
  while ((row= mysql_fetch_row(tableres)))
 
3426
  {
 
3427
    if (strcmp(buf, row[0]) != 0)
 
3428
      first= 1;
 
3429
    if (first)
 
3430
    {
 
3431
      if (!opt_xml && opt_comments)
 
3432
      {
 
3433
        fprintf(md_result_file,"\n--\n-- Logfile group: %s\n--\n", row[0]);
 
3434
        check_io(md_result_file);
 
3435
      }
 
3436
      fprintf(md_result_file, "\nCREATE");
 
3437
    }
 
3438
    else
 
3439
    {
 
3440
      fprintf(md_result_file, "\nALTER");
 
3441
    }
 
3442
    fprintf(md_result_file,
 
3443
            " LOGFILE GROUP %s\n"
 
3444
            "  ADD UNDOFILE '%s'\n",
 
3445
            row[0],
 
3446
            row[1]);
 
3447
    if (first)
 
3448
    {
 
3449
      ubs= strstr(row[5],extra_format);
 
3450
      if(!ubs)
 
3451
        break;
 
3452
      ubs+= strlen(extra_format);
 
3453
      endsemi= strstr(ubs,";");
 
3454
      if(endsemi)
 
3455
        endsemi[0]= '\0';
 
3456
      fprintf(md_result_file,
 
3457
              "  UNDO_BUFFER_SIZE %s\n",
 
3458
              ubs);
 
3459
    }
 
3460
    fprintf(md_result_file,
 
3461
            "  INITIAL_SIZE %s\n"
 
3462
            "  ENGINE=%s;\n",
 
3463
            row[3],
 
3464
            row[4]);
 
3465
    check_io(md_result_file);
 
3466
    if (first)
 
3467
    {
 
3468
      first= 0;
 
3469
      strxmov(buf, row[0], NullS);
 
3470
    }
 
3471
  }
 
3472
  dynstr_free(&sqlbuf);
 
3473
  mysql_free_result(tableres);
 
3474
  init_dynamic_string_checked(&sqlbuf,
 
3475
                      "SELECT DISTINCT TABLESPACE_NAME,"
 
3476
                      " FILE_NAME,"
 
3477
                      " LOGFILE_GROUP_NAME,"
 
3478
                      " EXTENT_SIZE,"
 
3479
                      " INITIAL_SIZE,"
 
3480
                      " ENGINE"
 
3481
                      " FROM INFORMATION_SCHEMA.FILES"
 
3482
                      " WHERE FILE_TYPE = 'DATAFILE'",
 
3483
                      256, 1024);
 
3484
 
 
3485
  if(ts_where)
 
3486
    dynstr_append_checked(&sqlbuf, ts_where);
 
3487
 
 
3488
  dynstr_append_checked(&sqlbuf, " ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME");
 
3489
 
 
3490
  if (mysql_query_with_error_report(mysql, &tableres, sqlbuf.str))
 
3491
  {
 
3492
    dynstr_free(&sqlbuf);
 
3493
    DBUG_RETURN(1);
 
3494
  }
 
3495
 
 
3496
  buf[0]= 0;
 
3497
  while ((row= mysql_fetch_row(tableres)))
 
3498
  {
 
3499
    if (strcmp(buf, row[0]) != 0)
 
3500
      first= 1;
 
3501
    if (first)
 
3502
    {
 
3503
      if (!opt_xml && opt_comments)
 
3504
      {
 
3505
        fprintf(md_result_file,"\n--\n-- Tablespace: %s\n--\n", row[0]);
 
3506
        check_io(md_result_file);
 
3507
      }
 
3508
      fprintf(md_result_file, "\nCREATE");
 
3509
    }
 
3510
    else
 
3511
    {
 
3512
      fprintf(md_result_file, "\nALTER");
 
3513
    }
 
3514
    fprintf(md_result_file,
 
3515
            " TABLESPACE %s\n"
 
3516
            "  ADD DATAFILE '%s'\n",
 
3517
            row[0],
 
3518
            row[1]);
 
3519
    if (first)
 
3520
    {
 
3521
      fprintf(md_result_file,
 
3522
              "  USE LOGFILE GROUP %s\n"
 
3523
              "  EXTENT_SIZE %s\n",
 
3524
              row[2],
 
3525
              row[3]);
 
3526
    }
 
3527
    fprintf(md_result_file,
 
3528
            "  INITIAL_SIZE %s\n"
 
3529
            "  ENGINE=%s;\n",
 
3530
            row[4],
 
3531
            row[5]);
 
3532
    check_io(md_result_file);
 
3533
    if (first)
 
3534
    {
 
3535
      first= 0;
 
3536
      strxmov(buf, row[0], NullS);
 
3537
    }
 
3538
  }
 
3539
 
 
3540
  mysql_free_result(tableres);
 
3541
  dynstr_free(&sqlbuf);
 
3542
  DBUG_RETURN(0);
 
3543
}
 
3544
 
 
3545
static int dump_all_databases()
 
3546
{
 
3547
  MYSQL_ROW row;
 
3548
  MYSQL_RES *tableres;
 
3549
  int result=0;
 
3550
 
 
3551
  if (mysql_query_with_error_report(mysql, &tableres, "SHOW DATABASES"))
 
3552
    return 1;
 
3553
  while ((row= mysql_fetch_row(tableres)))
 
3554
  {
 
3555
    if (dump_all_tables_in_db(row[0]))
 
3556
      result=1;
 
3557
  }
 
3558
  if (seen_views)
 
3559
  {
 
3560
    if (mysql_query(mysql, "SHOW DATABASES") ||
 
3561
        !(tableres= mysql_store_result(mysql)))
 
3562
    {
 
3563
      my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
 
3564
                      MYF(0), mysql_error(mysql));
 
3565
      return 1;
 
3566
    }
 
3567
    while ((row= mysql_fetch_row(tableres)))
 
3568
    {
 
3569
      if (dump_all_views_in_db(row[0]))
 
3570
        result=1;
 
3571
    }
 
3572
  }
 
3573
  return result;
 
3574
}
 
3575
/* dump_all_databases */
 
3576
 
 
3577
 
 
3578
static int dump_databases(char **db_names)
 
3579
{
 
3580
  int result=0;
 
3581
  char **db;
 
3582
  DBUG_ENTER("dump_databases");
 
3583
 
 
3584
  for (db= db_names ; *db ; db++)
 
3585
  {
 
3586
    if (dump_all_tables_in_db(*db))
 
3587
      result=1;
 
3588
  }
 
3589
  if (!result && seen_views)
 
3590
  {
 
3591
    for (db= db_names ; *db ; db++)
 
3592
    {
 
3593
      if (dump_all_views_in_db(*db))
 
3594
        result=1;
 
3595
    }
 
3596
  }
 
3597
  DBUG_RETURN(result);
 
3598
} /* dump_databases */
 
3599
 
 
3600
 
 
3601
/*
 
3602
View Specific database initalization.
 
3603
 
 
3604
SYNOPSIS
 
3605
  init_dumping_views
 
3606
  qdatabase      quoted name of the database
 
3607
 
 
3608
RETURN VALUES
 
3609
  0        Success.
 
3610
  1        Failure.
 
3611
*/
 
3612
int init_dumping_views(char *qdatabase __attribute__((unused)))
 
3613
{
 
3614
    return 0;
 
3615
} /* init_dumping_views */
 
3616
 
 
3617
 
 
3618
/*
 
3619
Table Specific database initalization.
 
3620
 
 
3621
SYNOPSIS
 
3622
  init_dumping_tables
 
3623
  qdatabase      quoted name of the database
 
3624
 
 
3625
RETURN VALUES
 
3626
  0        Success.
 
3627
  1        Failure.
 
3628
*/
 
3629
 
 
3630
int init_dumping_tables(char *qdatabase)
 
3631
{
 
3632
  DBUG_ENTER("init_dumping_tables");
 
3633
 
 
3634
  if (!opt_create_db)
 
3635
  {
 
3636
    char qbuf[256];
 
3637
    MYSQL_ROW row;
 
3638
    MYSQL_RES *dbinfo;
 
3639
 
 
3640
    my_snprintf(qbuf, sizeof(qbuf),
 
3641
                "SHOW CREATE DATABASE IF NOT EXISTS %s",
 
3642
                qdatabase);
 
3643
 
 
3644
    if (mysql_query(mysql, qbuf) || !(dbinfo = mysql_store_result(mysql)))
 
3645
    {
 
3646
      /* Old server version, dump generic CREATE DATABASE */
 
3647
      if (opt_drop_database)
 
3648
        fprintf(md_result_file,
 
3649
                "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
 
3650
                qdatabase);
 
3651
      fprintf(md_result_file,
 
3652
              "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
 
3653
              qdatabase);
 
3654
    }
 
3655
    else
 
3656
    {
 
3657
      if (opt_drop_database)
 
3658
        fprintf(md_result_file,
 
3659
                "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
 
3660
                qdatabase);
 
3661
      row = mysql_fetch_row(dbinfo);
 
3662
      if (row[1])
 
3663
      {
 
3664
        fprintf(md_result_file,"\n%s;\n",row[1]);
 
3665
      }
 
3666
      mysql_free_result(dbinfo);
 
3667
    }
 
3668
  }
 
3669
  DBUG_RETURN(0);
 
3670
} /* init_dumping_tables */
 
3671
 
 
3672
 
 
3673
static int init_dumping(char *database, int init_func(char*))
 
3674
{
 
3675
  if (mysql_get_server_version(mysql) >= 50003 &&
 
3676
      !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
 
3677
    return 1;
 
3678
 
 
3679
  if (mysql_select_db(mysql, database))
 
3680
  {
 
3681
    DB_error(mysql, "when selecting the database");
 
3682
    return 1;                   /* If --force */
 
3683
  }
 
3684
  if (!path && !opt_xml)
 
3685
  {
 
3686
    if (opt_databases || opt_alldbs)
 
3687
    {
 
3688
      /*
 
3689
        length of table name * 2 (if name contains quotes), 2 quotes and 0
 
3690
      */
 
3691
      char quoted_database_buf[NAME_LEN*2+3];
 
3692
      char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
 
3693
      if (opt_comments)
 
3694
      {
 
3695
        fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
 
3696
        check_io(md_result_file);
 
3697
      }
 
3698
 
 
3699
      /* Call the view or table specific function */
 
3700
      init_func(qdatabase);
 
3701
 
 
3702
      fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
 
3703
      check_io(md_result_file);
 
3704
    }
 
3705
  }
 
3706
  if (extended_insert)
 
3707
    init_dynamic_string_checked(&extended_row, "", 1024, 1024);
 
3708
  return 0;
 
3709
} /* init_dumping */
 
3710
 
 
3711
 
 
3712
/* Return 1 if we should copy the table */
 
3713
 
 
3714
my_bool include_table(const uchar *hash_key, size_t len)
 
3715
{
 
3716
  return !hash_search(&ignore_table, hash_key, len);
 
3717
}
 
3718
 
 
3719
 
 
3720
static int dump_all_tables_in_db(char *database)
 
3721
{
 
3722
  char *table;
 
3723
  uint numrows;
 
3724
  char table_buff[NAME_LEN*2+3];
 
3725
  char hash_key[2*NAME_LEN+2];  /* "db.tablename" */
 
3726
  char *afterdot;
 
3727
  int using_mysql_db= my_strcasecmp(&my_charset_latin1, database, "mysql");
 
3728
  DBUG_ENTER("dump_all_tables_in_db");
 
3729
 
 
3730
  afterdot= strmov(hash_key, database);
 
3731
  *afterdot++= '.';
 
3732
 
 
3733
  if (init_dumping(database, init_dumping_tables))
 
3734
    DBUG_RETURN(1);
 
3735
  if (opt_xml)
 
3736
    print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
 
3737
  if (lock_tables)
 
3738
  {
 
3739
    DYNAMIC_STRING query;
 
3740
    init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
 
3741
    for (numrows= 0 ; (table= getTableName(1)) ; )
 
3742
    {
 
3743
      char *end= strmov(afterdot, table);
 
3744
      if (include_table((uchar*) hash_key,end - hash_key))
 
3745
      {
 
3746
        numrows++;
 
3747
        dynstr_append_checked(&query, quote_name(table, table_buff, 1));
 
3748
        dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
 
3749
      }
 
3750
    }
 
3751
    if (numrows && mysql_real_query(mysql, query.str, query.length-1))
 
3752
      DB_error(mysql, "when using LOCK TABLES");
 
3753
            /* We shall continue here, if --force was given */
 
3754
    dynstr_free(&query);
 
3755
  }
 
3756
  if (flush_logs)
 
3757
  {
 
3758
    if (mysql_refresh(mysql, REFRESH_LOG))
 
3759
      DB_error(mysql, "when doing refresh");
 
3760
           /* We shall continue here, if --force was given */
 
3761
  }
 
3762
  while ((table= getTableName(0)))
 
3763
  {
 
3764
    char *end= strmov(afterdot, table);
 
3765
    if (include_table((uchar*) hash_key, end - hash_key))
 
3766
    {
 
3767
      dump_table(table,database);
 
3768
      my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
 
3769
      order_by= 0;
 
3770
    }
 
3771
  }
 
3772
  if (opt_events && !opt_xml &&
 
3773
      mysql_get_server_version(mysql) >= 50106)
 
3774
  {
 
3775
    DBUG_PRINT("info", ("Dumping events for database %s", database));
 
3776
    dump_events_for_db(database);
 
3777
  }
 
3778
  if (opt_routines && !opt_xml &&
 
3779
      mysql_get_server_version(mysql) >= 50009)
 
3780
  {
 
3781
    DBUG_PRINT("info", ("Dumping routines for database %s", database));
 
3782
    dump_routines_for_db(database);
 
3783
  }
 
3784
  if (opt_xml)
 
3785
  {
 
3786
    fputs("</database>\n", md_result_file);
 
3787
    check_io(md_result_file);
 
3788
  }
 
3789
  if (lock_tables)
 
3790
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
 
3791
  if (flush_privileges && using_mysql_db == 0)
 
3792
  {
 
3793
    fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n");
 
3794
    fprintf(md_result_file,"\n/*! FLUSH PRIVILEGES */;\n");
 
3795
  }
 
3796
  DBUG_RETURN(0);
 
3797
} /* dump_all_tables_in_db */
 
3798
 
 
3799
 
 
3800
/*
 
3801
   dump structure of views of database
 
3802
 
 
3803
   SYNOPSIS
 
3804
     dump_all_views_in_db()
 
3805
     database  database name
 
3806
 
 
3807
  RETURN
 
3808
    0 OK
 
3809
    1 ERROR
 
3810
*/
 
3811
 
 
3812
static my_bool dump_all_views_in_db(char *database)
 
3813
{
 
3814
  char *table;
 
3815
  uint numrows;
 
3816
  char table_buff[NAME_LEN*2+3];
 
3817
  char hash_key[2*NAME_LEN+2];  /* "db.tablename" */
 
3818
  char *afterdot;
 
3819
 
 
3820
  afterdot= strmov(hash_key, database);
 
3821
  *afterdot++= '.';
 
3822
 
 
3823
  if (init_dumping(database, init_dumping_views))
 
3824
    return 1;
 
3825
  if (opt_xml)
 
3826
    print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
 
3827
  if (lock_tables)
 
3828
  {
 
3829
    DYNAMIC_STRING query;
 
3830
    init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
 
3831
    for (numrows= 0 ; (table= getTableName(1)); )
 
3832
    {
 
3833
      char *end= strmov(afterdot, table);
 
3834
      if (include_table((uchar*) hash_key,end - hash_key))
 
3835
      {
 
3836
        numrows++;
 
3837
        dynstr_append_checked(&query, quote_name(table, table_buff, 1));
 
3838
        dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
 
3839
      }
 
3840
    }
 
3841
    if (numrows && mysql_real_query(mysql, query.str, query.length-1))
 
3842
      DB_error(mysql, "when using LOCK TABLES");
 
3843
            /* We shall continue here, if --force was given */
 
3844
    dynstr_free(&query);
 
3845
  }
 
3846
  if (flush_logs)
 
3847
  {
 
3848
    if (mysql_refresh(mysql, REFRESH_LOG))
 
3849
      DB_error(mysql, "when doing refresh");
 
3850
           /* We shall continue here, if --force was given */
 
3851
  }
 
3852
  while ((table= getTableName(0)))
 
3853
  {
 
3854
    char *end= strmov(afterdot, table);
 
3855
    if (include_table((uchar*) hash_key, end - hash_key))
 
3856
      get_view_structure(table, database);
 
3857
  }
 
3858
  if (opt_xml)
 
3859
  {
 
3860
    fputs("</database>\n", md_result_file);
 
3861
    check_io(md_result_file);
 
3862
  }
 
3863
  if (lock_tables)
 
3864
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
 
3865
  return 0;
 
3866
} /* dump_all_tables_in_db */
 
3867
 
 
3868
 
 
3869
/*
 
3870
  get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
 
3871
  table name from the server for the table name given on the command line.
 
3872
  we do this because the table name given on the command line may be a
 
3873
  different case (e.g.  T1 vs t1)
 
3874
 
 
3875
  RETURN
 
3876
    pointer to the table name
 
3877
    0 if error
 
3878
*/
 
3879
 
 
3880
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
 
3881
{
 
3882
  char *name= 0;
 
3883
  MYSQL_RES  *table_res;
 
3884
  MYSQL_ROW  row;
 
3885
  char query[50 + 2*NAME_LEN];
 
3886
  char show_name_buff[FN_REFLEN];
 
3887
  DBUG_ENTER("get_actual_table_name");
 
3888
 
 
3889
  /* Check memory for quote_for_like() */
 
3890
  DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
 
3891
  my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
 
3892
              quote_for_like(old_table_name, show_name_buff));
 
3893
 
 
3894
  if (mysql_query_with_error_report(mysql, 0, query))
 
3895
    return NullS;
 
3896
 
 
3897
  if ((table_res= mysql_store_result(mysql)))
 
3898
  {
 
3899
    my_ulonglong num_rows= mysql_num_rows(table_res);
 
3900
    if (num_rows > 0)
 
3901
    {
 
3902
      ulong *lengths;
 
3903
      /*
 
3904
        Return first row
 
3905
        TODO: Return all matching rows
 
3906
      */
 
3907
      row= mysql_fetch_row(table_res);
 
3908
      lengths= mysql_fetch_lengths(table_res);
 
3909
      name= strmake_root(root, row[0], lengths[0]);
 
3910
    }
 
3911
    mysql_free_result(table_res);
 
3912
  }
 
3913
  DBUG_PRINT("exit", ("new_table_name: %s", name));
 
3914
  DBUG_RETURN(name);
 
3915
}
 
3916
 
 
3917
 
 
3918
static int dump_selected_tables(char *db, char **table_names, int tables)
 
3919
{
 
3920
  char table_buff[NAME_LEN*2+3];
 
3921
  DYNAMIC_STRING lock_tables_query;
 
3922
  MEM_ROOT root;
 
3923
  char **dump_tables, **pos, **end;
 
3924
  DBUG_ENTER("dump_selected_tables");
 
3925
 
 
3926
  if (init_dumping(db, init_dumping_tables))
 
3927
    DBUG_RETURN(1);
 
3928
 
 
3929
  init_alloc_root(&root, 8192, 0);
 
3930
  if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
 
3931
     die(EX_EOM, "alloc_root failure.");
 
3932
 
 
3933
  init_dynamic_string_checked(&lock_tables_query, "LOCK TABLES ", 256, 1024);
 
3934
  for (; tables > 0 ; tables-- , table_names++)
 
3935
  {
 
3936
    /* the table name passed on commandline may be wrong case */
 
3937
    if ((*pos= get_actual_table_name(*table_names, &root)))
 
3938
    {
 
3939
      /* Add found table name to lock_tables_query */
 
3940
      if (lock_tables)
 
3941
      {
 
3942
        dynstr_append_checked(&lock_tables_query, quote_name(*pos, table_buff, 1));
 
3943
        dynstr_append_checked(&lock_tables_query, " READ /*!32311 LOCAL */,");
 
3944
      }
 
3945
      pos++;
 
3946
    }
 
3947
    else
 
3948
    {
 
3949
      if (!ignore_errors)
 
3950
      {
 
3951
        dynstr_free(&lock_tables_query);
 
3952
        free_root(&root, MYF(0));
 
3953
      }
 
3954
      maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
 
3955
      /* We shall countinue here, if --force was given */
 
3956
    }
 
3957
  }
 
3958
  end= pos;
 
3959
 
 
3960
  if (lock_tables)
 
3961
  {
 
3962
    if (mysql_real_query(mysql, lock_tables_query.str,
 
3963
                         lock_tables_query.length-1))
 
3964
    {
 
3965
      if (!ignore_errors)
 
3966
      {
 
3967
        dynstr_free(&lock_tables_query);
 
3968
        free_root(&root, MYF(0));
 
3969
      }
 
3970
      DB_error(mysql, "when doing LOCK TABLES");
 
3971
       /* We shall countinue here, if --force was given */
 
3972
    }
 
3973
  }
 
3974
  dynstr_free(&lock_tables_query);
 
3975
  if (flush_logs)
 
3976
  {
 
3977
    if (mysql_refresh(mysql, REFRESH_LOG))
 
3978
    {
 
3979
      if (!ignore_errors)
 
3980
        free_root(&root, MYF(0));
 
3981
      DB_error(mysql, "when doing refresh");
 
3982
    }
 
3983
     /* We shall countinue here, if --force was given */
 
3984
  }
 
3985
  if (opt_xml)
 
3986
    print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NullS);
 
3987
 
 
3988
  /* Dump each selected table */
 
3989
  for (pos= dump_tables; pos < end; pos++)
 
3990
  {
 
3991
    DBUG_PRINT("info",("Dumping table %s", *pos));
 
3992
    dump_table(*pos, db);
 
3993
  }
 
3994
 
 
3995
  /* Dump each selected view */
 
3996
  if (seen_views)
 
3997
  {
 
3998
    for (pos= dump_tables; pos < end; pos++)
 
3999
      get_view_structure(*pos, db);
 
4000
  }
 
4001
  if (opt_events && !opt_xml &&
 
4002
      mysql_get_server_version(mysql) >= 50106)
 
4003
  {
 
4004
    DBUG_PRINT("info", ("Dumping events for database %s", db));
 
4005
    dump_events_for_db(db);
 
4006
  }
 
4007
  /* obtain dump of routines (procs/functions) */
 
4008
  if (opt_routines  && !opt_xml &&
 
4009
      mysql_get_server_version(mysql) >= 50009)
 
4010
  {
 
4011
    DBUG_PRINT("info", ("Dumping routines for database %s", db));
 
4012
    dump_routines_for_db(db);
 
4013
  }
 
4014
  free_root(&root, MYF(0));
 
4015
  my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
 
4016
  order_by= 0;
 
4017
  if (opt_xml)
 
4018
  {
 
4019
    fputs("</database>\n", md_result_file);
 
4020
    check_io(md_result_file);
 
4021
  }
 
4022
  if (lock_tables)
 
4023
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
 
4024
  DBUG_RETURN(0);
 
4025
} /* dump_selected_tables */
 
4026
 
 
4027
 
 
4028
static int do_show_master_status(MYSQL *mysql_con)
 
4029
{
 
4030
  MYSQL_ROW row;
 
4031
  MYSQL_RES *master;
 
4032
  const char *comment_prefix=
 
4033
    (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
 
4034
  if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
 
4035
  {
 
4036
    return 1;
 
4037
  }
 
4038
  else
 
4039
  {
 
4040
    row= mysql_fetch_row(master);
 
4041
    if (row && row[0] && row[1])
 
4042
    {
 
4043
      /* SHOW MASTER STATUS reports file and position */
 
4044
      if (opt_comments)
 
4045
        fprintf(md_result_file,
 
4046
                "\n--\n-- Position to start replication or point-in-time "
 
4047
                "recovery from\n--\n\n");
 
4048
      fprintf(md_result_file,
 
4049
              "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
 
4050
              comment_prefix, row[0], row[1]);
 
4051
      check_io(md_result_file);
 
4052
    }
 
4053
    else if (!ignore_errors)
 
4054
    {
 
4055
      /* SHOW MASTER STATUS reports nothing and --force is not enabled */
 
4056
      my_printf_error(0, "Error: Binlogging on server not active",
 
4057
                      MYF(0));
 
4058
      mysql_free_result(master);
 
4059
      maybe_exit(EX_MYSQLERR);
 
4060
      return 1;
 
4061
    }
 
4062
    mysql_free_result(master);
 
4063
  }
 
4064
  return 0;
 
4065
}
 
4066
 
 
4067
static int do_stop_slave_sql(MYSQL *mysql_con)
 
4068
{
 
4069
  MYSQL_RES *slave;
 
4070
  /* We need to check if the slave sql is running in the first place */
 
4071
  if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
 
4072
    return(1);
 
4073
  else
 
4074
  {
 
4075
    MYSQL_ROW row= mysql_fetch_row(slave);
 
4076
    if (row && row[11])
 
4077
    {
 
4078
      /* if SLAVE SQL is not running, we don't stop it */
 
4079
      if (!strcmp(row[11],"No"))
 
4080
      {
 
4081
        mysql_free_result(slave);
 
4082
        /* Silently assume that they don't have the slave running */
 
4083
        return(0);
 
4084
      }
 
4085
    }
 
4086
  }
 
4087
  mysql_free_result(slave);
 
4088
 
 
4089
  /* now, stop slave if running */
 
4090
  if (mysql_query_with_error_report(mysql_con, 0, "STOP SLAVE SQL_THREAD"))
 
4091
    return(1);
 
4092
 
 
4093
  return(0);
 
4094
}
 
4095
 
 
4096
static int add_stop_slave(void)
 
4097
{
 
4098
  if (opt_comments)
 
4099
    fprintf(md_result_file,
 
4100
            "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
 
4101
  fprintf(md_result_file, "STOP SLAVE;\n");
 
4102
  return(0);
 
4103
}
 
4104
 
 
4105
static int add_slave_statements(void)
 
4106
{
 
4107
  if (opt_comments)
 
4108
    fprintf(md_result_file,
 
4109
            "\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
 
4110
  fprintf(md_result_file, "START SLAVE;\n");
 
4111
  return(0);
 
4112
}
 
4113
 
 
4114
static int do_show_slave_status(MYSQL *mysql_con)
 
4115
{
 
4116
  MYSQL_RES *slave;
 
4117
  const char *comment_prefix=
 
4118
    (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
 
4119
  if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
 
4120
  {
 
4121
    if (!ignore_errors)
 
4122
    {
 
4123
      /* SHOW SLAVE STATUS reports nothing and --force is not enabled */
 
4124
      my_printf_error(0, "Error: Slave not set up", MYF(0));
 
4125
    }
 
4126
    return 1;
 
4127
  }
 
4128
  else
 
4129
  {
 
4130
    MYSQL_ROW row= mysql_fetch_row(slave);
 
4131
    if (row && row[9] && row[21])
 
4132
    {
 
4133
      /* SHOW MASTER STATUS reports file and position */
 
4134
      if (opt_comments)
 
4135
        fprintf(md_result_file,
 
4136
                "\n--\n-- Position to start replication or point-in-time "
 
4137
                "recovery from (the master of this slave)\n--\n\n");
 
4138
 
 
4139
      fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
 
4140
 
 
4141
      if (opt_include_master_host_port)
 
4142
      {
 
4143
        if (row[1])
 
4144
          fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
 
4145
        if (row[3])
 
4146
          fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
 
4147
      }
 
4148
      fprintf(md_result_file,
 
4149
              "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
 
4150
 
 
4151
      check_io(md_result_file);
 
4152
    }
 
4153
    mysql_free_result(slave);
 
4154
  }
 
4155
  return 0;
 
4156
}
 
4157
 
 
4158
static int do_start_slave_sql(MYSQL *mysql_con)
 
4159
{
 
4160
  MYSQL_RES *slave;
 
4161
  /* We need to check if the slave sql is stopped in the first place */
 
4162
  if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
 
4163
    return(1);
 
4164
  else
 
4165
  {
 
4166
    MYSQL_ROW row= mysql_fetch_row(slave);
 
4167
    if (row && row[11])
 
4168
    {
 
4169
      /* if SLAVE SQL is not running, we don't start it */
 
4170
      if (!strcmp(row[11],"Yes"))
 
4171
      {
 
4172
        mysql_free_result(slave);
 
4173
        /* Silently assume that they don't have the slave running */
 
4174
        return(0);
 
4175
      }
 
4176
    }
 
4177
  }
 
4178
  mysql_free_result(slave);
 
4179
 
 
4180
  /* now, start slave if stopped */
 
4181
  if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE"))
 
4182
  {
 
4183
    my_printf_error(0, "Error: Unable to start slave", MYF(0));
 
4184
    return 1;
 
4185
  }
 
4186
  return(0);
 
4187
}
 
4188
 
 
4189
 
 
4190
 
 
4191
static int do_flush_tables_read_lock(MYSQL *mysql_con)
 
4192
{
 
4193
  /*
 
4194
    We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
 
4195
    will wait but will not stall the whole mysqld, and when the long update is
 
4196
    done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
 
4197
    FLUSH TABLES is to lower the probability of a stage where both mysqldump
 
4198
    and most client connections are stalled. Of course, if a second long
 
4199
    update starts between the two FLUSHes, we have that bad stall.
 
4200
  */
 
4201
  return
 
4202
    ( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") ||
 
4203
      mysql_query_with_error_report(mysql_con, 0,
 
4204
                                    "FLUSH TABLES WITH READ LOCK") );
 
4205
}
 
4206
 
 
4207
 
 
4208
static int do_unlock_tables(MYSQL *mysql_con)
 
4209
{
 
4210
  return mysql_query_with_error_report(mysql_con, 0, "UNLOCK TABLES");
 
4211
}
 
4212
 
 
4213
static int get_bin_log_name(MYSQL *mysql_con,
 
4214
                            char* buff_log_name, uint buff_len)
 
4215
{
 
4216
  MYSQL_RES *res;
 
4217
  MYSQL_ROW row;
 
4218
 
 
4219
  if (mysql_query(mysql_con, "SHOW MASTER STATUS") ||
 
4220
      !(res= mysql_store_result(mysql)))
 
4221
    return 1;
 
4222
 
 
4223
  if (!(row= mysql_fetch_row(res)))
 
4224
  {
 
4225
    mysql_free_result(res);
 
4226
    return 1;
 
4227
  }
 
4228
  /*
 
4229
    Only one row is returned, and the first column is the name of the
 
4230
    active log.
 
4231
  */
 
4232
  strmake(buff_log_name, row[0], buff_len - 1);
 
4233
 
 
4234
  mysql_free_result(res);
 
4235
  return 0;
 
4236
}
 
4237
 
 
4238
static int purge_bin_logs_to(MYSQL *mysql_con, char* log_name)
 
4239
{
 
4240
  DYNAMIC_STRING str;
 
4241
  int err;
 
4242
  init_dynamic_string_checked(&str, "PURGE BINARY LOGS TO '", 1024, 1024);
 
4243
  dynstr_append_checked(&str, log_name);
 
4244
  dynstr_append_checked(&str, "'");
 
4245
  err = mysql_query_with_error_report(mysql_con, 0, str.str);
 
4246
  dynstr_free(&str);
 
4247
  return err;
 
4248
}
 
4249
 
 
4250
 
 
4251
static int start_transaction(MYSQL *mysql_con)
 
4252
{
 
4253
  /*
 
4254
    We use BEGIN for old servers. --single-transaction --master-data will fail
 
4255
    on old servers, but that's ok as it was already silently broken (it didn't
 
4256
    do a consistent read, so better tell people frankly, with the error).
 
4257
 
 
4258
    We want the first consistent read to be used for all tables to dump so we
 
4259
    need the REPEATABLE READ level (not anything lower, for example READ
 
4260
    COMMITTED would give one new consistent read per dumped table).
 
4261
  */
 
4262
  if ((mysql_get_server_version(mysql_con) < 40100) && opt_master_data)
 
4263
  {
 
4264
    fprintf(stderr, "-- %s: the combination of --single-transaction and "
 
4265
            "--master-data requires a MySQL server version of at least 4.1 "
 
4266
            "(current server's version is %s). %s\n",
 
4267
            ignore_errors ? "Warning" : "Error",
 
4268
            mysql_con->server_version ? mysql_con->server_version : "unknown",
 
4269
            ignore_errors ? "Continuing due to --force, backup may not be consistent across all tables!" : "Aborting.");
 
4270
    if (!ignore_errors)
 
4271
      exit(EX_MYSQLERR);
 
4272
  }
 
4273
 
 
4274
  return (mysql_query_with_error_report(mysql_con, 0,
 
4275
                                        "SET SESSION TRANSACTION ISOLATION "
 
4276
                                        "LEVEL REPEATABLE READ") ||
 
4277
          mysql_query_with_error_report(mysql_con, 0,
 
4278
                                        "START TRANSACTION "
 
4279
                                        "/*!40100 WITH CONSISTENT SNAPSHOT */"));
 
4280
}
 
4281
 
 
4282
 
 
4283
static ulong find_set(TYPELIB *lib, const char *x, uint length,
 
4284
                      char **err_pos, uint *err_len)
 
4285
{
 
4286
  const char *end= x + length;
 
4287
  ulong found= 0;
 
4288
  uint find;
 
4289
  char buff[255];
 
4290
 
 
4291
  *err_pos= 0;                  /* No error yet */
 
4292
  while (end > x && my_isspace(charset_info, end[-1]))
 
4293
    end--;
 
4294
 
 
4295
  *err_len= 0;
 
4296
  if (x != end)
 
4297
  {
 
4298
    const char *start= x;
 
4299
    for (;;)
 
4300
    {
 
4301
      const char *pos= start;
 
4302
      uint var_len;
 
4303
 
 
4304
      for (; pos != end && *pos != ','; pos++) ;
 
4305
      var_len= (uint) (pos - start);
 
4306
      strmake(buff, start, min(sizeof(buff), var_len));
 
4307
      find= find_type(buff, lib, var_len);
 
4308
      if (!find)
 
4309
      {
 
4310
        *err_pos= (char*) start;
 
4311
        *err_len= var_len;
 
4312
      }
 
4313
      else
 
4314
        found|= ((longlong) 1 << (find - 1));
 
4315
      if (pos == end)
 
4316
        break;
 
4317
      start= pos + 1;
 
4318
    }
 
4319
  }
 
4320
  return found;
 
4321
}
 
4322
 
 
4323
 
 
4324
/* Print a value with a prefix on file */
 
4325
static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
 
4326
                        const char *prefix, const char *name,
 
4327
                        int string_value)
 
4328
{
 
4329
  MYSQL_FIELD   *field;
 
4330
  mysql_field_seek(result, 0);
 
4331
 
 
4332
  for ( ; (field= mysql_fetch_field(result)) ; row++)
 
4333
  {
 
4334
    if (!strcmp(field->name,name))
 
4335
    {
 
4336
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
4337
      {
 
4338
        fputc(' ',file);
 
4339
        fputs(prefix, file);
 
4340
        if (string_value)
 
4341
          unescape(file,row[0],(uint) strlen(row[0]));
 
4342
        else
 
4343
          fputs(row[0], file);
 
4344
        check_io(file);
 
4345
        return;
 
4346
      }
 
4347
    }
 
4348
  }
 
4349
  return;                                       /* This shouldn't happen */
 
4350
} /* print_value */
 
4351
 
 
4352
 
 
4353
/*
 
4354
  SYNOPSIS
 
4355
 
 
4356
  Check if we the table is one of the table types that should be ignored:
 
4357
  MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
 
4358
  If the table should be altogether ignored, it returns a TRUE, FALSE if it
 
4359
  should not be ignored. If the user has selected to use INSERT DELAYED, it
 
4360
  sets the value of the bool pointer supports_delayed_inserts to 0 if not
 
4361
  supported, 1 if it is supported.
 
4362
 
 
4363
  ARGS
 
4364
 
 
4365
    check_if_ignore_table()
 
4366
    table_name                  Table name to check
 
4367
    table_type                  Type of table
 
4368
 
 
4369
  GLOBAL VARIABLES
 
4370
    mysql                       MySQL connection
 
4371
    verbose                     Write warning messages
 
4372
 
 
4373
  RETURN
 
4374
    char (bit value)            See IGNORE_ values at top
 
4375
*/
 
4376
 
 
4377
char check_if_ignore_table(const char *table_name, char *table_type)
 
4378
{
 
4379
  char result= IGNORE_NONE;
 
4380
  char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
 
4381
  MYSQL_RES *res= NULL;
 
4382
  MYSQL_ROW row;
 
4383
  DBUG_ENTER("check_if_ignore_table");
 
4384
 
 
4385
  /* Check memory for quote_for_like() */
 
4386
  DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff));
 
4387
  my_snprintf(buff, sizeof(buff), "show table status like %s",
 
4388
              quote_for_like(table_name, show_name_buff));
 
4389
  if (mysql_query_with_error_report(mysql, &res, buff))
 
4390
  {
 
4391
    if (mysql_errno(mysql) != ER_PARSE_ERROR)
 
4392
    {                                   /* If old MySQL version */
 
4393
      verbose_msg("-- Warning: Couldn't get status information for "
 
4394
                  "table %s (%s)\n", table_name, mysql_error(mysql));
 
4395
      DBUG_RETURN(result);                       /* assume table is ok */
 
4396
    }
 
4397
  }
 
4398
  if (!(row= mysql_fetch_row(res)))
 
4399
  {
 
4400
    fprintf(stderr,
 
4401
            "Error: Couldn't read status information for table %s (%s)\n",
 
4402
            table_name, mysql_error(mysql));
 
4403
    mysql_free_result(res);
 
4404
    DBUG_RETURN(result);                         /* assume table is ok */
 
4405
  }
 
4406
  if (!(row[1]))
 
4407
    strmake(table_type, "VIEW", NAME_LEN-1);
 
4408
  else
 
4409
  {
 
4410
    /*
 
4411
      If the table type matches any of these, we do support delayed inserts.
 
4412
      Note: we do not want to skip dumping this table if if is not one of
 
4413
      these types, but we do want to use delayed inserts in the dump if
 
4414
      the table type is _NOT_ one of these types
 
4415
    */
 
4416
    strmake(table_type, row[1], NAME_LEN-1);
 
4417
    if (opt_delayed)
 
4418
    {
 
4419
      if (strcmp(table_type,"MyISAM") &&
 
4420
          strcmp(table_type,"ISAM") &&
 
4421
          strcmp(table_type,"ARCHIVE") &&
 
4422
          strcmp(table_type,"HEAP") &&
 
4423
          strcmp(table_type,"MEMORY"))
 
4424
        result= IGNORE_INSERT_DELAYED;
 
4425
    }
 
4426
 
 
4427
    /*
 
4428
      If these two types, we do want to skip dumping the table
 
4429
    */
 
4430
    if (!opt_no_data &&
 
4431
        (!my_strcasecmp(&my_charset_latin1, table_type, "MRG_MyISAM") ||
 
4432
         !strcmp(table_type,"MRG_ISAM")))
 
4433
      result= IGNORE_DATA;
 
4434
  }
 
4435
  mysql_free_result(res);
 
4436
  DBUG_RETURN(result);
 
4437
}
 
4438
 
 
4439
 
 
4440
/*
 
4441
  Get string of comma-separated primary key field names
 
4442
 
 
4443
  SYNOPSIS
 
4444
    char *primary_key_fields(const char *table_name)
 
4445
    RETURNS     pointer to allocated buffer (must be freed by caller)
 
4446
    table_name  quoted table name
 
4447
 
 
4448
  DESCRIPTION
 
4449
    Use SHOW KEYS FROM table_name, allocate a buffer to hold the
 
4450
    field names, and then build that string and return the pointer
 
4451
    to that buffer.
 
4452
 
 
4453
    Returns NULL if there is no PRIMARY or UNIQUE key on the table,
 
4454
    or if there is some failure.  It is better to continue to dump
 
4455
    the table unsorted, rather than exit without dumping the data.
 
4456
*/
 
4457
 
 
4458
static char *primary_key_fields(const char *table_name)
 
4459
{
 
4460
  MYSQL_RES  *res= NULL;
 
4461
  MYSQL_ROW  row;
 
4462
  /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
 
4463
  char show_keys_buff[15 + NAME_LEN * 2 + 3];
 
4464
  uint result_length= 0;
 
4465
  char *result= 0;
 
4466
  char buff[NAME_LEN * 2 + 3];
 
4467
  char *quoted_field;
 
4468
 
 
4469
  my_snprintf(show_keys_buff, sizeof(show_keys_buff),
 
4470
              "SHOW KEYS FROM %s", table_name);
 
4471
  if (mysql_query(mysql, show_keys_buff) ||
 
4472
      !(res= mysql_store_result(mysql)))
 
4473
  {
 
4474
    fprintf(stderr, "Warning: Couldn't read keys from table %s;"
 
4475
            " records are NOT sorted (%s)\n",
 
4476
            table_name, mysql_error(mysql));
 
4477
    /* Don't exit, because it's better to print out unsorted records */
 
4478
    goto cleanup;
 
4479
  }
 
4480
 
 
4481
  /*
 
4482
   * Figure out the length of the ORDER BY clause result.
 
4483
   * Note that SHOW KEYS is ordered:  a PRIMARY key is always the first
 
4484
   * row, and UNIQUE keys come before others.  So we only need to check
 
4485
   * the first key, not all keys.
 
4486
   */
 
4487
  if ((row= mysql_fetch_row(res)) && atoi(row[1]) == 0)
 
4488
  {
 
4489
    /* Key is unique */
 
4490
    do
 
4491
    {
 
4492
      quoted_field= quote_name(row[4], buff, 0);
 
4493
      result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
 
4494
    } while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1);
 
4495
  }
 
4496
 
 
4497
  /* Build the ORDER BY clause result */
 
4498
  if (result_length)
 
4499
  {
 
4500
    char *end;
 
4501
    /* result (terminating \0 is already in result_length) */
 
4502
    result= my_malloc(result_length + 10, MYF(MY_WME));
 
4503
    if (!result)
 
4504
    {
 
4505
      fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n");
 
4506
      goto cleanup;
 
4507
    }
 
4508
    mysql_data_seek(res, 0);
 
4509
    row= mysql_fetch_row(res);
 
4510
    quoted_field= quote_name(row[4], buff, 0);
 
4511
    end= strmov(result, quoted_field);
 
4512
    while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1)
 
4513
    {
 
4514
      quoted_field= quote_name(row[4], buff, 0);
 
4515
      end= strxmov(end, ",", quoted_field, NullS);
 
4516
    }
 
4517
  }
 
4518
 
 
4519
cleanup:
 
4520
  if (res)
 
4521
    mysql_free_result(res);
 
4522
 
 
4523
  return result;
 
4524
}
 
4525
 
 
4526
 
 
4527
/*
 
4528
  Replace a substring
 
4529
 
 
4530
  SYNOPSIS
 
4531
    replace
 
4532
    ds_str      The string to search and perform the replace in
 
4533
    search_str  The string to search for
 
4534
    search_len  Length of the string to search for
 
4535
    replace_str The string to replace with
 
4536
    replace_len Length of the string to replace with
 
4537
 
 
4538
  RETURN
 
4539
    0 String replaced
 
4540
    1 Could not find search_str in str
 
4541
*/
 
4542
 
 
4543
static int replace(DYNAMIC_STRING *ds_str,
 
4544
                   const char *search_str, ulong search_len,
 
4545
                   const char *replace_str, ulong replace_len)
 
4546
{
 
4547
  DYNAMIC_STRING ds_tmp;
 
4548
  const char *start= strstr(ds_str->str, search_str);
 
4549
  if (!start)
 
4550
    return 1;
 
4551
  init_dynamic_string_checked(&ds_tmp, "",
 
4552
                      ds_str->length + replace_len, 256);
 
4553
  dynstr_append_mem_checked(&ds_tmp, ds_str->str, start - ds_str->str);
 
4554
  dynstr_append_mem_checked(&ds_tmp, replace_str, replace_len);
 
4555
  dynstr_append_checked(&ds_tmp, start + search_len);
 
4556
  dynstr_set_checked(ds_str, ds_tmp.str);
 
4557
  dynstr_free(&ds_tmp);
 
4558
  return 0;
 
4559
}
 
4560
 
 
4561
 
 
4562
/*
 
4563
  Getting VIEW structure
 
4564
 
 
4565
  SYNOPSIS
 
4566
    get_view_structure()
 
4567
    table   view name
 
4568
    db      db name
 
4569
 
 
4570
  RETURN
 
4571
    0 OK
 
4572
    1 ERROR
 
4573
*/
 
4574
 
 
4575
static my_bool get_view_structure(char *table, char* db)
 
4576
{
 
4577
  MYSQL_RES  *table_res;
 
4578
  MYSQL_ROW  row;
 
4579
  MYSQL_FIELD *field;
 
4580
  char       *result_table, *opt_quoted_table;
 
4581
  char       table_buff[NAME_LEN*2+3];
 
4582
  char       table_buff2[NAME_LEN*2+3];
 
4583
  char       query[QUERY_LENGTH];
 
4584
  FILE       *sql_file= md_result_file;
 
4585
  DBUG_ENTER("get_view_structure");
 
4586
 
 
4587
  if (opt_no_create_info) /* Don't write table creation info */
 
4588
    DBUG_RETURN(0);
 
4589
 
 
4590
  verbose_msg("-- Retrieving view structure for table %s...\n", table);
 
4591
 
 
4592
#ifdef NOT_REALLY_USED_YET
 
4593
  sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
 
4594
          (opt_quoted || opt_keywords));
 
4595
#endif
 
4596
 
 
4597
  result_table=     quote_name(table, table_buff, 1);
 
4598
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
4599
 
 
4600
  if (switch_character_set_results(mysql, "binary"))
 
4601
    DBUG_RETURN(1);
 
4602
 
 
4603
  my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %s", result_table);
 
4604
 
 
4605
  if (mysql_query_with_error_report(mysql, &table_res, query))
 
4606
  {
 
4607
    switch_character_set_results(mysql, default_charset);
 
4608
    DBUG_RETURN(0);
 
4609
  }
 
4610
 
 
4611
  /* Check if this is a view */
 
4612
  field= mysql_fetch_field_direct(table_res, 0);
 
4613
  if (strcmp(field->name, "View") != 0)
 
4614
  {
 
4615
    switch_character_set_results(mysql, default_charset);
 
4616
    verbose_msg("-- It's base table, skipped\n");
 
4617
    DBUG_RETURN(0);
 
4618
  }
 
4619
 
 
4620
  /* If requested, open separate .sql file for this view */
 
4621
  if (path)
 
4622
  {
 
4623
    if (!(sql_file= open_sql_file_for_table(table)))
 
4624
      DBUG_RETURN(1);
 
4625
 
 
4626
    write_header(sql_file, db);
 
4627
  }
 
4628
 
 
4629
  if (!opt_xml && opt_comments)
 
4630
  {
 
4631
    fprintf(sql_file, "\n--\n-- Final view structure for view %s\n--\n\n",
 
4632
            result_table);
 
4633
    check_io(sql_file);
 
4634
  }
 
4635
  fprintf(sql_file, "/*!50001 DROP TABLE %s*/;\n", opt_quoted_table);
 
4636
  if (opt_drop)
 
4637
  {
 
4638
    fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
 
4639
            opt_quoted_table);
 
4640
    check_io(sql_file);
 
4641
  }
 
4642
 
 
4643
 
 
4644
  my_snprintf(query, sizeof(query),
 
4645
              "SELECT CHECK_OPTION, DEFINER, SECURITY_TYPE, "
 
4646
              "       CHARACTER_SET_CLIENT, COLLATION_CONNECTION "
 
4647
              "FROM information_schema.views "
 
4648
              "WHERE table_name=\"%s\" AND table_schema=\"%s\"", table, db);
 
4649
 
 
4650
  if (mysql_query(mysql, query))
 
4651
  {
 
4652
    /*
 
4653
      Use the raw output from SHOW CREATE TABLE if
 
4654
       information_schema query fails.
 
4655
     */
 
4656
    row= mysql_fetch_row(table_res);
 
4657
    fprintf(sql_file, "/*!50001 %s */;\n", row[1]);
 
4658
    check_io(sql_file);
 
4659
    mysql_free_result(table_res);
 
4660
  }
 
4661
  else
 
4662
  {
 
4663
    char *ptr;
 
4664
    ulong *lengths;
 
4665
    char search_buf[256], replace_buf[256];
 
4666
    ulong search_len, replace_len;
 
4667
    DYNAMIC_STRING ds_view;
 
4668
 
 
4669
    /* Save the result of SHOW CREATE TABLE in ds_view */
 
4670
    row= mysql_fetch_row(table_res);
 
4671
    lengths= mysql_fetch_lengths(table_res);
 
4672
    init_dynamic_string_checked(&ds_view, row[1], lengths[1] + 1, 1024);
 
4673
    mysql_free_result(table_res);
 
4674
 
 
4675
    /* Get the result from "select ... information_schema" */
 
4676
    if (!(table_res= mysql_store_result(mysql)) ||
 
4677
        !(row= mysql_fetch_row(table_res)))
 
4678
    {
 
4679
      if (table_res)
 
4680
        mysql_free_result(table_res);
 
4681
      dynstr_free(&ds_view);
 
4682
      DB_error(mysql, "when trying to save the result of SHOW CREATE TABLE in ds_view.");
 
4683
      DBUG_RETURN(1);
 
4684
    }
 
4685
 
 
4686
    lengths= mysql_fetch_lengths(table_res);
 
4687
 
 
4688
    /*
 
4689
      "WITH %s CHECK OPTION" is available from 5.0.2
 
4690
      Surround it with !50002 comments
 
4691
    */
 
4692
    if (strcmp(row[0], "NONE"))
 
4693
    {
 
4694
 
 
4695
      ptr= search_buf;
 
4696
      search_len= (ulong)(strxmov(ptr, "WITH ", row[0],
 
4697
                                  " CHECK OPTION", NullS) - ptr);
 
4698
      ptr= replace_buf;
 
4699
      replace_len=(ulong)(strxmov(ptr, "*/\n/*!50002 WITH ", row[0],
 
4700
                                  " CHECK OPTION", NullS) - ptr);
 
4701
      replace(&ds_view, search_buf, search_len, replace_buf, replace_len);
 
4702
    }
 
4703
 
 
4704
    /*
 
4705
      "DEFINER=%s SQL SECURITY %s" is available from 5.0.13
 
4706
      Surround it with !50013 comments
 
4707
    */
 
4708
    {
 
4709
      size_t     user_name_len;
 
4710
      char       user_name_str[USERNAME_LENGTH + 1];
 
4711
      char       quoted_user_name_str[USERNAME_LENGTH * 2 + 3];
 
4712
      size_t     host_name_len;
 
4713
      char       host_name_str[HOSTNAME_LENGTH + 1];
 
4714
      char       quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
 
4715
 
 
4716
      parse_user(row[1], lengths[1], user_name_str, &user_name_len,
 
4717
                 host_name_str, &host_name_len);
 
4718
 
 
4719
      ptr= search_buf;
 
4720
      search_len=
 
4721
        (ulong)(strxmov(ptr, "DEFINER=",
 
4722
                        quote_name(user_name_str, quoted_user_name_str, FALSE),
 
4723
                        "@",
 
4724
                        quote_name(host_name_str, quoted_host_name_str, FALSE),
 
4725
                        " SQL SECURITY ", row[2], NullS) - ptr);
 
4726
      ptr= replace_buf;
 
4727
      replace_len=
 
4728
        (ulong)(strxmov(ptr, "*/\n/*!50013 DEFINER=",
 
4729
                        quote_name(user_name_str, quoted_user_name_str, FALSE),
 
4730
                        "@",
 
4731
                        quote_name(host_name_str, quoted_host_name_str, FALSE),
 
4732
                        " SQL SECURITY ", row[2],
 
4733
                        " */\n/*!50001", NullS) - ptr);
 
4734
      replace(&ds_view, search_buf, search_len, replace_buf, replace_len);
 
4735
    }
 
4736
 
 
4737
    /* Dump view structure to file */
 
4738
 
 
4739
    fprintf(sql_file,
 
4740
            "/*!50001 SET @saved_cs_client          = @@character_set_client */;\n"
 
4741
            "/*!50001 SET @saved_cs_results         = @@character_set_results */;\n"
 
4742
            "/*!50001 SET @saved_col_connection     = @@collation_connection */;\n"
 
4743
            "/*!50001 SET character_set_client      = %s */;\n"
 
4744
            "/*!50001 SET character_set_results     = %s */;\n"
 
4745
            "/*!50001 SET collation_connection      = %s */;\n"
 
4746
            "/*!50001 %s */;\n"
 
4747
            "/*!50001 SET character_set_client      = @saved_cs_client */;\n"
 
4748
            "/*!50001 SET character_set_results     = @saved_cs_results */;\n"
 
4749
            "/*!50001 SET collation_connection      = @saved_col_connection */;\n",
 
4750
            (const char *) row[3],
 
4751
            (const char *) row[3],
 
4752
            (const char *) row[4],
 
4753
            (const char *) ds_view.str);
 
4754
 
 
4755
    check_io(sql_file);
 
4756
    mysql_free_result(table_res);
 
4757
    dynstr_free(&ds_view);
 
4758
  }
 
4759
 
 
4760
  if (switch_character_set_results(mysql, default_charset))
 
4761
    DBUG_RETURN(1);
 
4762
 
 
4763
  /* If a separate .sql file was opened, close it now */
 
4764
  if (sql_file != md_result_file)
 
4765
  {
 
4766
    fputs("\n", sql_file);
 
4767
    write_footer(sql_file);
 
4768
    my_fclose(sql_file, MYF(MY_WME));
 
4769
  }
 
4770
  DBUG_RETURN(0);
 
4771
}
 
4772
 
 
4773
/*
 
4774
  The following functions are wrappers for the dynamic string functions
 
4775
  and if they fail, the wrappers will terminate the current process.
 
4776
*/
 
4777
 
 
4778
#define DYNAMIC_STR_ERROR_MSG "Couldn't perform DYNAMIC_STRING operation"
 
4779
 
 
4780
static void init_dynamic_string_checked(DYNAMIC_STRING *str, const char *init_str,
 
4781
                            uint init_alloc, uint alloc_increment)
 
4782
{
 
4783
  if (init_dynamic_string(str, init_str, init_alloc, alloc_increment))
 
4784
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
 
4785
}
 
4786
 
 
4787
static void dynstr_append_checked(DYNAMIC_STRING* dest, const char* src)
 
4788
{
 
4789
  if (dynstr_append(dest, src))
 
4790
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
 
4791
}
 
4792
 
 
4793
static void dynstr_set_checked(DYNAMIC_STRING *str, const char *init_str)
 
4794
{
 
4795
  if (dynstr_set(str, init_str))
 
4796
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
 
4797
}
 
4798
 
 
4799
static void dynstr_append_mem_checked(DYNAMIC_STRING *str, const char *append,
 
4800
                          uint length)
 
4801
{
 
4802
  if (dynstr_append_mem(str, append, length))
 
4803
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
 
4804
}
 
4805
 
 
4806
static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size)
 
4807
{
 
4808
  if (dynstr_realloc(str, additional_size))
 
4809
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
 
4810
}
 
4811
 
 
4812
 
 
4813
int main(int argc, char **argv)
 
4814
{
 
4815
  char bin_log_name[FN_REFLEN];
 
4816
  int exit_code;
 
4817
  MY_INIT("mysqldump");
 
4818
 
 
4819
  compatible_mode_normal_str[0]= 0;
 
4820
  default_charset= (char *)mysql_universal_client_charset;
 
4821
  bzero((char*) &ignore_table, sizeof(ignore_table));
 
4822
 
 
4823
  exit_code= get_options(&argc, &argv);
 
4824
  if (exit_code)
 
4825
  {
 
4826
    free_resources(0);
 
4827
    exit(exit_code);
 
4828
  }
 
4829
 
 
4830
  if (log_error_file)
 
4831
  {
 
4832
    if(!(stderror_file= freopen(log_error_file, "a+", stderr)))
 
4833
    {
 
4834
      free_resources(0);
 
4835
      exit(EX_MYSQLERR);
 
4836
    }
 
4837
  }
 
4838
 
 
4839
  if (connect_to_db(current_host, current_user, opt_password))
 
4840
  {
 
4841
    free_resources(0);
 
4842
    exit(EX_MYSQLERR);
 
4843
  }
 
4844
  if (!path)
 
4845
    write_header(md_result_file, *argv);
 
4846
 
 
4847
  if (opt_slave_data && do_stop_slave_sql(mysql))
 
4848
    goto err;
 
4849
 
 
4850
  if ((opt_lock_all_tables || opt_master_data) &&
 
4851
      do_flush_tables_read_lock(mysql))
 
4852
    goto err;
 
4853
  if (opt_single_transaction && start_transaction(mysql))
 
4854
      goto err;
 
4855
  if (opt_delete_master_logs)
 
4856
  {
 
4857
    if (mysql_refresh(mysql, REFRESH_LOG) ||
 
4858
        get_bin_log_name(mysql, bin_log_name, sizeof(bin_log_name)))
 
4859
      goto err;
 
4860
    flush_logs= 0;
 
4861
  }
 
4862
  if (opt_lock_all_tables || opt_master_data)
 
4863
  {
 
4864
    if (flush_logs && mysql_refresh(mysql, REFRESH_LOG))
 
4865
      goto err;
 
4866
    flush_logs= 0; /* not anymore; that would not be sensible */
 
4867
  }
 
4868
  /* Add 'STOP SLAVE to beginning of dump */
 
4869
  if (opt_slave_apply && add_stop_slave())
 
4870
    goto err;
 
4871
  if (opt_master_data && do_show_master_status(mysql))
 
4872
    goto err;
 
4873
  if (opt_slave_data && do_show_slave_status(mysql))
 
4874
    goto err;
 
4875
  if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */
 
4876
    goto err;
 
4877
 
 
4878
  if (opt_alltspcs)
 
4879
    dump_all_tablespaces();
 
4880
 
 
4881
  if (opt_alldbs)
 
4882
  {
 
4883
    if (!opt_alltspcs && !opt_notspcs)
 
4884
      dump_all_tablespaces();
 
4885
    dump_all_databases();
 
4886
  }
 
4887
  else if (argc > 1 && !opt_databases)
 
4888
  {
 
4889
    /* Only one database and selected table(s) */
 
4890
    if (!opt_alltspcs && !opt_notspcs)
 
4891
      dump_tablespaces_for_tables(*argv, (argv + 1), (argc -1));
 
4892
    dump_selected_tables(*argv, (argv + 1), (argc - 1));
 
4893
  }
 
4894
  else
 
4895
  {
 
4896
    /* One or more databases, all tables */
 
4897
    if (!opt_alltspcs && !opt_notspcs)
 
4898
      dump_tablespaces_for_databases(argv);
 
4899
    dump_databases(argv);
 
4900
  }
 
4901
 
 
4902
  /* if --dump-slave , start the slave sql thread */
 
4903
  if (opt_slave_data && do_start_slave_sql(mysql))
 
4904
    goto err;
 
4905
 
 
4906
  /* add 'START SLAVE' to end of dump */
 
4907
  if (opt_slave_apply && add_slave_statements())
 
4908
    goto err;
 
4909
 
 
4910
  /* ensure dumped data flushed */
 
4911
  if (md_result_file && fflush(md_result_file))
 
4912
  {
 
4913
    if (!first_error)
 
4914
      first_error= EX_MYSQLERR;
 
4915
    goto err;
 
4916
  }
 
4917
  /* everything successful, purge the old logs files */
 
4918
  if (opt_delete_master_logs && purge_bin_logs_to(mysql, bin_log_name))
 
4919
    goto err;
 
4920
 
 
4921
#ifdef HAVE_SMEM
 
4922
  my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
 
4923
#endif
 
4924
  /*
 
4925
    No reason to explicitely COMMIT the transaction, neither to explicitely
 
4926
    UNLOCK TABLES: these will be automatically be done by the server when we
 
4927
    disconnect now. Saves some code here, some network trips, adds nothing to
 
4928
    server.
 
4929
  */
 
4930
err:
 
4931
  dbDisconnect(current_host);
 
4932
  if (!path)
 
4933
    write_footer(md_result_file);
 
4934
  free_resources();
 
4935
 
 
4936
  if (stderror_file)
 
4937
    fclose(stderror_file);
 
4938
 
 
4939
  return(first_error);
 
4940
} /* main */