~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqldump.c

  • Committer: Brian Aker
  • Date: 2008-07-03 00:14:39 UTC
  • Revision ID: brian@tangent.org-20080703001439-pit0mcl0wk8elxlq
Cleanup of sql-common and mysqldump

Show diffs side-by-side

added added

removed removed

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