~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.c

  • Committer: Monty Taylor
  • Date: 2008-07-26 16:51:58 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080726165158-qneg06kyisawnt3d
Added drizzle.pot. Not 100% on best practice here, but this seems ok.

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