~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Brian Aker
  • Date: 2009-11-11 15:49:59 UTC
  • mto: This revision was merged to the branch mainline in revision 1212.
  • Revision ID: brian@gaz-20091111154959-jqu64e48gp9ig3tp
Updating with my change to to DECIMAL from NEWDECIMAL and Stewart's update
for protobuf to correctly store DECIMAL

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
2
 
 * Copyright (C) 2010 Vijay Samuel
3
 
 * Copyright (C) 2010 Andrew Hutchings
4
 
 
5
 
  This program is free software; you can redistribute it and/or modify
6
 
  it under the terms of the GNU General Public License as published by
7
 
  the Free Software Foundation; version 2 of the License.
8
 
 
9
 
  This program is distributed in the hope that it will be useful,
10
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
  GNU General Public License for more details.
13
 
 
14
 
  You should have received a copy of the GNU General Public License
15
 
  along with this program; if not, write to the Free Software
16
 
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
17
15
 
18
16
/* drizzledump.cc  - Dump a tables contents and format to an ASCII file
19
17
 
20
18
 * 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
 
19
**
 
20
** The author's original notes follow :-
 
21
**
 
22
** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
 
23
** DATE:   December 3, 1994
 
24
** WARRANTY: None, expressed, impressed, implied
 
25
**          or other
 
26
** STATUS: Public domain
29
27
 
30
 
 * and more work by Monty, Jani & Sinisa
31
 
 * and all the MySQL developers over the years.
 
28
* and more work by Monty, Jani & Sinisa
 
29
* and all the MySQL developers over the years.
32
30
*/
33
31
 
34
32
#include "client_priv.h"
35
33
#include <string>
36
 
#include <iostream>
 
34
 
 
35
#include <mysys/my_sys.h>
 
36
#include <mystrings/m_string.h>
 
37
#include <mystrings/m_ctype.h>
 
38
#include "drizzled/hash.h"
37
39
#include <stdarg.h>
38
 
#include <boost/unordered_set.hpp>
39
40
#include <algorithm>
40
 
#include <fstream>
 
41
 
41
42
#include <drizzled/gettext.h>
42
 
#include <drizzled/configmake.h>
 
43
 
43
44
#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
45
 
51
46
using namespace std;
52
 
using namespace drizzled;
53
 
namespace po= boost::program_options;
54
47
 
55
48
/* Exit codes */
56
49
 
72
65
 
73
66
/* Size of buffer for dump's select query */
74
67
#define QUERY_LENGTH 1536
 
68
#define DRIZZLE_MAX_LINE_LENGTH 1024*1024L-1025
75
69
 
76
70
/* ignore table flags */
77
71
#define IGNORE_NONE 0x00 /* no ignore */
78
72
#define IGNORE_DATA 0x01 /* don't dump data for this table */
79
73
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
80
74
 
81
 
bool opt_alltspcs= false;
82
 
bool opt_complete_insert= false;
83
 
bool  verbose= false;
84
 
static bool use_drizzle_protocol= false;
85
 
bool ignore_errors= false;
 
75
static void add_load_option(string &str, const char *option,
 
76
                            const char *option_value);
 
77
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
 
78
                         char **err_pos, uint32_t *err_len);
 
79
 
 
80
static void field_escape(string &in, const char *from);
 
81
static bool  verbose= false;
 
82
static bool opt_no_create_info= false;
 
83
static bool opt_no_data= false;
 
84
static bool quick= true;
 
85
static bool extended_insert= true;
 
86
static bool ignore_errors= false;
86
87
static bool flush_logs= false;
 
88
static bool opt_drop= true; 
 
89
static bool opt_keywords= false;
 
90
static bool opt_compress= false;
 
91
static bool opt_delayed= false; 
87
92
static bool create_options= true; 
88
93
static bool opt_quoted= false;
89
 
bool opt_databases= false; 
90
 
bool opt_alldbs= false; 
 
94
static bool opt_databases= false; 
 
95
static bool opt_alldbs= false; 
 
96
static bool opt_create_db= false;
91
97
static bool opt_lock_all_tables= false;
 
98
static bool opt_set_charset= false; 
92
99
static bool opt_dump_date= true;
93
 
bool opt_autocommit= false; 
 
100
static bool opt_autocommit= false; 
 
101
static bool opt_disable_keys= true;
 
102
static bool opt_xml= false;
 
103
static bool tty_password= false;
94
104
static bool opt_single_transaction= false; 
95
 
static bool opt_comments;
96
 
static bool opt_compact;
97
 
bool opt_ignore= false;
98
 
bool opt_drop_database;
99
 
bool opt_no_create_info;
100
 
bool opt_no_data= false;
101
 
bool opt_create_db= false;
102
 
bool opt_disable_keys= true;
103
 
bool extended_insert= true;
104
 
bool opt_replace_into= false;
105
 
bool opt_drop= true; 
106
 
uint32_t show_progress_size= 0;
 
105
static bool opt_comments= false;
 
106
static bool opt_compact= false;
 
107
static bool opt_hex_blob= false;
 
108
static bool opt_order_by_primary=false; 
 
109
static bool opt_ignore= false;
 
110
static bool opt_complete_insert= false;
 
111
static bool opt_drop_database= false;
 
112
static bool opt_replace_into= false;
 
113
static bool opt_routines= false;
 
114
static bool opt_alltspcs= false;
 
115
static bool debug_info_flag= false;
 
116
static bool debug_check_flag= false;
 
117
static uint32_t show_progress_size= 0;
 
118
static uint64_t total_rows= 0;
 
119
static drizzle_st drizzle;
 
120
static drizzle_con_st dcon;
107
121
static string insert_pat;
 
122
static char  *opt_password= NULL;
 
123
static char *current_user= NULL;
 
124
static char  *current_host= NULL;
 
125
static char *path= NULL;
 
126
static char *fields_terminated= NULL;
 
127
static char *lines_terminated= NULL; 
 
128
static char *enclosed= NULL;
 
129
static char *opt_enclosed= NULL;
 
130
static char *escaped= NULL;
 
131
static char *where= NULL; 
 
132
static char *order_by= NULL;
 
133
static char *opt_compatible_mode_str= NULL;
 
134
static char *err_ptr= NULL;
 
135
static char **defaults_argv= NULL;
 
136
static char compatible_mode_normal_str[255];
 
137
static uint32_t opt_compatible_mode= 0;
108
138
static uint32_t opt_drizzle_port= 0;
 
139
static uint32_t my_end_arg;
109
140
static int first_error= 0;
110
141
static string extended_row;
111
142
FILE *md_result_file= 0;
112
143
FILE *stderror_file= 0;
113
 
std::vector<DrizzleDumpDatabase*> database_store;
114
 
DrizzleDumpConnection* db_connection;
115
 
DrizzleDumpConnection* destination_connection;
116
 
 
117
 
enum destinations {
118
 
  DESTINATION_DB,
119
 
  DESTINATION_FILES,
120
 
  DESTINATION_STDOUT
121
 
};
122
 
 
123
 
int opt_destination= DESTINATION_STDOUT;
124
 
std::string opt_destination_host;
125
 
uint16_t opt_destination_port;
126
 
std::string opt_destination_user;
127
 
std::string opt_destination_password;
128
 
std::string opt_destination_database;
129
 
 
130
 
const string progname= "drizzledump";
131
 
 
132
 
string password,
133
 
  enclosed,
134
 
  escaped,
135
 
  current_host,
136
 
  path,
137
 
  current_user,
138
 
  opt_password,
139
 
  opt_protocol,
140
 
  where;
141
 
 
142
 
//static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
143
 
 
144
 
boost::unordered_set<string> ignore_table;
145
 
 
146
 
void maybe_exit(int error);
 
144
 
 
145
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
 
146
 
 
147
static const char *compatible_mode_names[]=
 
148
{
 
149
  "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
 
150
  "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
 
151
  "ANSI",
 
152
  NULL
 
153
};
 
154
static TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
 
155
                                  "", compatible_mode_names, NULL};
 
156
 
 
157
drizzled::hash_set<string> ignore_table;
 
158
 
 
159
static struct my_option my_long_options[] =
 
160
{
 
161
  {"all", 'a', "Deprecated. Use --create-options instead.",
 
162
   (char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
 
163
   0, 0, 0, 0, 0},
 
164
  {"all-databases", 'A',
 
165
   "Dump all the databases. This will be same as --databases with all databases selected.",
 
166
   (char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
167
   0, 0},
 
168
  {"all-tablespaces", 'Y',
 
169
   "Dump all the tablespaces.",
 
170
   (char**) &opt_alltspcs, (char**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
171
   0, 0},
 
172
  {"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
 
173
   (char**) &opt_drop_database, (char**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
 
174
   0},
 
175
  {"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
 
176
   (char**) &opt_drop, (char**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
 
177
   0},
 
178
  {"allow-keywords", OPT_KEYWORDS,
 
179
   "Allow creation of column names that are keywords.", (char**) &opt_keywords,
 
180
   (char**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
181
  {"comments", 'i', "Write additional information.",
 
182
   (char**) &opt_comments, (char**) &opt_comments, 0, GET_BOOL, NO_ARG,
 
183
   1, 0, 0, 0, 0, 0},
 
184
  {"compatible", OPT_COMPATIBLE,
 
185
   "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.",
 
186
   (char**) &opt_compatible_mode_str, (char**) &opt_compatible_mode_str, 0,
 
187
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
188
  {"compact", OPT_COMPACT,
 
189
   "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",
 
190
   (char**) &opt_compact, (char**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
191
   0, 0},
 
192
  {"complete-insert", 'c', "Use complete insert statements.",
 
193
   (char**) &opt_complete_insert, (char**) &opt_complete_insert, 0, GET_BOOL,
 
194
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
195
  {"compress", 'C', "Use compression in server/client protocol.",
 
196
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
197
   0, 0, 0},
 
198
  {"create-options", OPT_CREATE_OPTIONS,
 
199
   "Include all DRIZZLE specific create options.",
 
200
   (char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1,
 
201
   0, 0, 0, 0, 0},
 
202
  {"databases", 'B',
 
203
   "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.",
 
204
   (char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
 
205
   0, 0, 0, 0},
 
206
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
 
207
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
 
208
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
209
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
 
210
   (char**) &debug_info_flag, (char**) &debug_info_flag,
 
211
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
212
  {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
 
213
   (char**) &opt_delayed, (char**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
214
   0, 0},
 
215
  {"disable-keys", 'K',
 
216
   "'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will be put in the output.", (char**) &opt_disable_keys,
 
217
   (char**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
218
  {"extended-insert", 'e',
 
219
   "Allows utilization of the new, much faster INSERT syntax.",
 
220
   (char**) &extended_insert, (char**) &extended_insert, 0, GET_BOOL, NO_ARG,
 
221
   1, 0, 0, 0, 0, 0},
 
222
  {"fields-terminated-by", OPT_FTB,
 
223
   "Fields in the textfile are terminated by ...", (char**) &fields_terminated,
 
224
   (char**) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
225
  {"fields-enclosed-by", OPT_ENC,
 
226
   "Fields in the importfile are enclosed by ...", (char**) &enclosed,
 
227
   (char**) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
 
228
  {"fields-optionally-enclosed-by", OPT_O_ENC,
 
229
   "Fields in the i.file are opt. enclosed by ...", (char**) &opt_enclosed,
 
230
   (char**) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
 
231
  {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
 
232
   (char**) &escaped, (char**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
233
  {"flush-logs", 'F', "Flush logs file in server before starting dump. "
 
234
   "Note that if you dump many databases at once (using the option "
 
235
   "--databases= or --all-databases), the logs will be flushed for "
 
236
   "each database dumped. The exception is when using --lock-all-tables "
 
237
   "in this case the logs will be flushed only once, corresponding "
 
238
   "to the moment all tables are locked. So if you want your dump and "
 
239
   "the log flush to happen at the same exact moment you should use "
 
240
   "--lock-all-tables or --flush-logs",
 
241
   (char**) &flush_logs, (char**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
242
   0, 0},
 
243
  {"force", 'f', "Continue even if we get an sql-error.",
 
244
   (char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG,
 
245
   0, 0, 0, 0, 0, 0},
 
246
  {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
 
247
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
248
  {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
 
249
    "VARBINARY, BLOB) in hexadecimal format.",
 
250
   (char**) &opt_hex_blob, (char**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
251
  {"host", 'h', "Connect to host.", (char**) &current_host,
 
252
   (char**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
253
  {"ignore-table", OPT_IGNORE_TABLE,
 
254
   "Do not dump the specified table. To specify more than one table to ignore, "
 
255
   "use the directive multiple times, once for each table.  Each table must "
 
256
   "be specified with both database and table names, e.g. --ignore-table=database.table",
 
257
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
258
  {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
 
259
   (char**) &opt_ignore, (char**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
260
   0, 0},
 
261
  {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
 
262
   (char**) &lines_terminated, (char**) &lines_terminated, 0, GET_STR,
 
263
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
264
  {"lock-all-tables", 'x', "Locks all tables across all databases. This "
 
265
   "is achieved by taking a global read lock for the duration of the whole "
 
266
   "dump. Automatically turns --single-transaction and --lock-tables off.",
 
267
   (char**) &opt_lock_all_tables, (char**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
 
268
   0, 0, 0, 0, 0, 0},
 
269
  {"no-autocommit", OPT_AUTOCOMMIT,
 
270
   "Wrap tables with autocommit/commit statements.",
 
271
   (char**) &opt_autocommit, (char**) &opt_autocommit, 0, GET_BOOL, NO_ARG,
 
272
   0, 0, 0, 0, 0, 0},
 
273
  {"no-create-db", 'n',
 
274
   "'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.}.",
 
275
   (char**) &opt_create_db, (char**) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
 
276
   0, 0, 0, 0},
 
277
  {"no-create-info", 't', "Don't write table creation info.",
 
278
   (char**) &opt_no_create_info, (char**) &opt_no_create_info, 0, GET_BOOL,
 
279
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
280
  {"no-data", 'd', "No row information.", (char**) &opt_no_data,
 
281
   (char**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
282
  {"no-set-names", 'N',
 
283
   "Deprecated. Use --skip-set-charset instead.",
 
284
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
285
  {"opt", OPT_OPTIMIZE,
 
286
   "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.",
 
287
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
288
  {"order-by-primary", OPT_ORDER_BY_PRIMARY,
 
289
   "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.",
 
290
   (char**) &opt_order_by_primary, (char**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
291
  {"password", 'P',
 
292
   "Password to use when connecting to server. If password is not given it's solicited on the tty.",
 
293
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
294
  {"port", 'p', "Port number to use for connection.", 
 
295
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
296
  {"quick", 'q', "Don't buffer query, dump directly to stdout.",
 
297
   (char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
298
  {"quote-names",'Q', "Quote table and column names with backticks (`).",
 
299
   (char**) &opt_quoted, (char**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
 
300
   0, 0},
 
301
  {"replace", OPT_DRIZZLE_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.",
 
302
   (char**) &opt_replace_into, (char**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
303
   0, 0},
 
304
  {"result-file", 'r',
 
305
   "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).",
 
306
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
307
  {"routines", 'R', "Dump stored routines (functions and procedures).",
 
308
     (char**) &opt_routines, (char**) &opt_routines, 0, GET_BOOL,
 
309
     NO_ARG, 0, 0, 0, 0, 0, 0},
 
310
  {"single-transaction", OPT_TRANSACTION,
 
311
   "Creates a consistent snapshot by dumping all tables in a single "
 
312
   "transaction. Works ONLY for tables stored in storage engines which "
 
313
   "support multiversioning (currently only InnoDB does); the dump is NOT "
 
314
   "guaranteed to be consistent for other storage engines. "
 
315
   "While a --single-transaction dump is in process, to ensure a valid "
 
316
   "dump file (correct table contents), no other "
 
317
   "connection should use the following statements: ALTER TABLE, DROP "
 
318
   "TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not "
 
319
   "isolated from them. Option automatically turns off --lock-tables.",
 
320
   (char**) &opt_single_transaction, (char**) &opt_single_transaction, 0,
 
321
   GET_BOOL, NO_ARG,  0, 0, 0, 0, 0, 0},
 
322
  {"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
 
323
   (char**) &opt_dump_date, (char**) &opt_dump_date, 0,
 
324
   GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
325
  {"skip-opt", OPT_SKIP_OPTIMIZATION,
 
326
   "Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
 
327
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
328
  {"tab",'T',
 
329
   "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.",
 
330
   (char**) &path, (char**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
331
  {"tables", OPT_TABLES, "Overrides option --databases (-B).",
 
332
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
333
  {"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of rows before each output progress report (requires --verbose)."),
 
334
   (char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
 
335
   10000, 0, 0, 0, 0, 0},
 
336
  {"user", 'u', "User for login if not current user.",
 
337
   (char**) &current_user, (char**) &current_user, 0, GET_STR, REQUIRED_ARG,
 
338
   0, 0, 0, 0, 0, 0},
 
339
  {"verbose", 'v', "Print info about the various stages.",
 
340
   (char**) &verbose, (char**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
341
  {"version",'V', "Output version information and exit.", 0, 0, 0,
 
342
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
343
  {"where", 'w', "Dump only selected records; QUOTES mandatory!",
 
344
   (char**) &where, (char**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
345
  {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
 
346
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
347
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
348
};
 
349
 
 
350
static const char *load_default_groups[]= { "drizzledump","client",0 };
 
351
 
 
352
static void maybe_exit(int error);
147
353
static void die(int error, const char* reason, ...);
148
 
static void write_header(char *db_name);
149
 
static int dump_selected_tables(const string &db, const vector<string> &table_names);
150
 
static int dump_databases(const vector<string> &db_names);
 
354
static void maybe_die(int error, const char* reason, ...);
 
355
static void write_header(FILE *sql_file, char *db_name);
 
356
static void print_value(FILE *file, drizzle_result_st *result,
 
357
                        drizzle_row_t row, const char *prefix, const char *name,
 
358
                        int string_value);
 
359
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row,
 
360
                                   const char* name);
 
361
static int dump_selected_tables(char *db, char **table_names, int tables);
 
362
static int dump_all_tables_in_db(char *db);
 
363
static int init_dumping_tables(char *);
 
364
static int init_dumping(char *, int init_func(char*));
 
365
static int dump_databases(char **);
151
366
static int dump_all_databases(void);
152
 
int get_server_type();
153
 
void dump_all_tables(void);
154
 
void generate_dump(void);
155
 
void generate_dump_db(void);
156
 
 
157
 
void dump_all_tables(void)
158
 
{
159
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
160
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
161
 
  {
162
 
    if ((not (*i)->populateTables()) && (not ignore_errors))
163
 
      maybe_exit(EX_DRIZZLEERR);
164
 
  }
165
 
}
166
 
 
167
 
void generate_dump(void)
168
 
{
169
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
170
 
 
171
 
  if (path.empty())
172
 
  {
173
 
    cout << endl << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;"
174
 
      << endl << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
175
 
  }
176
 
 
177
 
  if (opt_autocommit)
178
 
    cout << "SET AUTOCOMMIT=0;" << endl;
179
 
 
180
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
181
 
  {
182
 
    DrizzleDumpDatabase *database= *i;
183
 
    cout << *database;
184
 
  }
185
 
 
186
 
  if (path.empty())
187
 
  {
188
 
    cout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;"
189
 
      << endl << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
190
 
  }
191
 
}
192
 
 
193
 
void generate_dump_db(void)
194
 
{
195
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
196
 
  DrizzleStringBuf sbuf(1024);
197
 
  try
198
 
  {
199
 
    destination_connection= new DrizzleDumpConnection(opt_destination_host,
200
 
      opt_destination_port, opt_destination_user, opt_destination_password,
201
 
      false);
202
 
  }
203
 
  catch (std::exception&)
204
 
  {
205
 
    cerr << "Could not connect to destination database server" << endl;
206
 
    maybe_exit(EX_DRIZZLEERR);
207
 
  }
208
 
  sbuf.setConnection(destination_connection);
209
 
  std::ostream sout(&sbuf);
210
 
  sout.exceptions(ios_base::badbit);
211
 
 
212
 
  if (path.empty())
213
 
  {
214
 
    sout << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;" << endl;
215
 
    sout << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
216
 
  }
217
 
 
218
 
  if (opt_autocommit)
219
 
    cout << "SET AUTOCOMMIT=0;" << endl;
220
 
 
221
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
222
 
  {
223
 
    try
224
 
    {
225
 
      DrizzleDumpDatabase *database= *i;
226
 
      sout << *database;
227
 
    }
228
 
    catch (std::exception&)
229
 
    {
230
 
      std::cout << _("Error inserting into destination database") << std::endl;
231
 
      if (not ignore_errors)
232
 
        maybe_exit(EX_DRIZZLEERR);
233
 
    }
234
 
  }
235
 
 
236
 
  if (path.empty())
237
 
  {
238
 
    sout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;" << endl;
239
 
    sout << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
240
 
  }
 
367
static char *quote_name(const char *name, char *buff, bool force);
 
368
char check_if_ignore_table(const char *table_name, char *table_type);
 
369
static char *primary_key_fields(const char *table_name);
 
370
 
 
371
/*
 
372
  Print the supplied message if in verbose mode
 
373
 
 
374
  SYNOPSIS
 
375
    verbose_msg()
 
376
    fmt   format specifier
 
377
    ...   variable number of parameters
 
378
*/
 
379
static void verbose_msg(const char *fmt, ...)
 
380
{
 
381
  va_list args;
 
382
 
 
383
 
 
384
  if (!verbose)
 
385
    return;
 
386
 
 
387
  va_start(args, fmt);
 
388
  vfprintf(stderr, fmt, args);
 
389
  va_end(args);
241
390
}
242
391
 
243
392
/*
244
393
  exit with message if ferror(file)
245
394
 
246
395
  SYNOPSIS
247
 
  check_io()
248
 
  file        - checked file
 
396
    check_io()
 
397
    file        - checked file
249
398
*/
250
399
 
251
400
static void check_io(FILE *file)
254
403
    die(EX_EOF, _("Got errno %d on write"), errno);
255
404
}
256
405
 
257
 
static void write_header(char *db_name)
258
 
{
259
 
  if ((not opt_compact) and (opt_comments))
260
 
  {
261
 
    cout << "-- drizzledump " << VERSION << " libdrizzle "
262
 
      << drizzle_version() << ", for " << HOST_VENDOR << "-" << HOST_OS
263
 
      << " (" << HOST_CPU << ")" << endl << "--" << endl;
264
 
    cout << "-- Host: " << current_host << "    Database: " << db_name << endl;
265
 
    cout << "-- ------------------------------------------------------" << endl;
266
 
    cout << "-- Server version\t" << db_connection->getServerVersion();
267
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
268
 
      cout << " (MySQL server)";
269
 
    else if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_DRIZZLE_FOUND)
270
 
      cout << " (Drizzle server)";
271
 
    cout << endl << endl;
 
406
static void print_version(void)
 
407
{
 
408
  printf(_("%s  Drizzle %s libdrizzle %s, for %s-%s (%s)\n"), my_progname,
 
409
         VERSION, drizzle_version(), HOST_VENDOR, HOST_OS, HOST_CPU);
 
410
} /* print_version */
 
411
 
 
412
 
 
413
static void short_usage_sub(void)
 
414
{
 
415
  printf(_("Usage: %s [OPTIONS] database [tables]\n"), my_progname);
 
416
  printf(_("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n"),
 
417
         my_progname);
 
418
  printf(_("OR     %s [OPTIONS] --all-databases [OPTIONS]\n"), my_progname);
 
419
}
 
420
 
 
421
 
 
422
static void usage(void)
 
423
{
 
424
  print_version();
 
425
  puts("");
 
426
  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"));
 
427
  puts(_("Dumps definitions and data from a Drizzle database server"));
 
428
  short_usage_sub();
 
429
  print_defaults("drizzle",load_default_groups);
 
430
  my_print_help(my_long_options);
 
431
  my_print_variables(my_long_options);
 
432
} /* usage */
 
433
 
 
434
 
 
435
static void short_usage(void)
 
436
{
 
437
  short_usage_sub();
 
438
  printf(_("For more options, use %s --help\n"), my_progname);
 
439
}
 
440
 
 
441
static void write_header(FILE *sql_file, char *db_name)
 
442
{
 
443
  if (opt_xml)
 
444
  {
 
445
    fputs("<?xml version=\"1.0\"?>\n", sql_file);
 
446
    /*
 
447
      Schema reference.  Allows use of xsi:nil for NULL values and
 
448
      xsi:type to define an element's data type.
 
449
    */
 
450
    fputs("<drizzledump ", sql_file);
 
451
    fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
 
452
          sql_file);
 
453
    fputs(">\n", sql_file);
 
454
    check_io(sql_file);
 
455
  }
 
456
  else if (!opt_compact)
 
457
  {
 
458
    if (opt_comments)
 
459
    {
 
460
      fprintf(sql_file,
 
461
              "-- drizzledump %s libdrizzle %s, for %s-%s (%s)\n--\n",
 
462
              VERSION, drizzle_version(), HOST_VENDOR, HOST_OS, HOST_CPU);
 
463
      fprintf(sql_file, "-- Host: %s    Database: %s\n",
 
464
              current_host ? current_host : "localhost", db_name ? db_name :
 
465
              "");
 
466
      fputs("-- ------------------------------------------------------\n",
 
467
            sql_file);
 
468
      fprintf(sql_file, "-- Server version\t%s\n",
 
469
              drizzle_con_server_version(&dcon));
 
470
    }
 
471
    if (opt_set_charset)
 
472
      fprintf(sql_file,
 
473
"\nSET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION;\n");
 
474
 
 
475
    if (path == NULL)
 
476
    {
 
477
      fprintf(md_result_file,"\
 
478
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;\n\
 
479
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;\n\
 
480
");
 
481
    }
 
482
    check_io(sql_file);
272
483
  }
273
484
} /* write_header */
274
485
 
275
486
 
276
487
static void write_footer(FILE *sql_file)
277
488
{
278
 
  if (! opt_compact)
279
 
  {
 
489
  if (opt_xml)
 
490
  {
 
491
    fputs("</drizzledump>\n", sql_file);
 
492
    check_io(sql_file);
 
493
  }
 
494
  else if (opt_compact == false)
 
495
  {
 
496
    if (path == NULL)
 
497
    {
 
498
      fprintf(md_result_file,"\
 
499
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;\n\
 
500
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;\n");
 
501
    }
 
502
    if (opt_set_charset)
 
503
      fprintf(sql_file, "SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION;\n");
280
504
    if (opt_comments)
281
505
    {
282
506
      if (opt_dump_date)
283
507
      {
284
 
        boost::posix_time::ptime time(boost::posix_time::second_clock::local_time());
 
508
        char time_str[20];
 
509
        get_date(time_str, GETDATE_DATE_TIME, 0);
285
510
        fprintf(sql_file, "-- Dump completed on %s\n",
286
 
          boost::posix_time::to_simple_string(time).c_str());
 
511
                time_str);
287
512
      }
288
513
      else
289
514
        fprintf(sql_file, "-- Dump completed\n");
292
517
  }
293
518
} /* write_footer */
294
519
 
295
 
static int get_options(void)
296
 
{
 
520
 
 
521
extern "C" bool get_one_option(int optid, const struct my_option *, char *argument);
 
522
 
 
523
extern "C" bool get_one_option(int optid, const struct my_option *, char *argument)
 
524
{
 
525
  char *endchar= NULL;
 
526
  uint64_t temp_drizzle_port= 0;
 
527
 
 
528
  switch (optid) {
 
529
  case 'p':
 
530
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
 
531
    /* if there is an alpha character this is not a valid port */
 
532
    if (strlen(endchar) != 0)
 
533
    {
 
534
      fprintf(stderr, _("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead.\n"));
 
535
      exit(EX_USAGE);
 
536
    }
 
537
    /* If the port number is > 65535 it is not a valid port
 
538
 *        This also helps with potential data loss casting unsigned long to a
 
539
 *               uint32_t. */
 
540
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
 
541
    {
 
542
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
 
543
      exit(EX_USAGE);
 
544
    }
 
545
    else
 
546
    {
 
547
      opt_drizzle_port= (uint32_t) temp_drizzle_port;
 
548
    }
 
549
    break;
 
550
  case 'P':
 
551
    if (argument)
 
552
    {
 
553
      char *start= argument;
 
554
      if (opt_password)
 
555
        free(opt_password);
 
556
      opt_password= strdup(argument);
 
557
      if (opt_password == NULL)
 
558
      {
 
559
        fprintf(stderr, _("Memory allocation error while copying password. "
 
560
                        "Aborting.\n"));
 
561
        exit(ENOMEM);
 
562
      }
 
563
      while (*argument)
 
564
      {
 
565
        /* Overwriting password with 'x' */
 
566
        *argument++= 'x';
 
567
      }
 
568
      if (*start)
 
569
      {
 
570
        /* Cut length of argument */
 
571
        start[1]= 0;
 
572
      }
 
573
      tty_password= 0;
 
574
    }
 
575
    else
 
576
    {
 
577
      tty_password= 1;
 
578
    }
 
579
    break;
 
580
  case 'r':
 
581
    if (!(md_result_file= fopen(argument, "w")))
 
582
      exit(1);
 
583
    break;
 
584
  case 'N':
 
585
    opt_set_charset= 0;
 
586
    break;
 
587
  case 'T':
 
588
    opt_disable_keys=0;
 
589
 
 
590
    if (strlen(argument) >= FN_REFLEN)
 
591
    {
 
592
      /*
 
593
        This check is made because the some the file functions below
 
594
        have FN_REFLEN sized stack allocated buffers and will cause
 
595
        a crash even if the input destination buffer is large enough
 
596
        to hold the output.
 
597
      */
 
598
      die(EX_USAGE, _("Input filename too long: %s"), argument);
 
599
    }
 
600
 
 
601
    break;
 
602
  case 'V': print_version(); exit(0);
 
603
  case 'X':
 
604
    opt_xml= 1;
 
605
    extended_insert= opt_drop=
 
606
      opt_disable_keys= opt_autocommit= opt_create_db= 0;
 
607
    break;
 
608
  case 'I':
 
609
  case '?':
 
610
    usage();
 
611
    exit(0);
 
612
  case (int) OPT_OPTIMIZE:
 
613
    extended_insert= opt_drop= quick= create_options=
 
614
      opt_disable_keys= opt_set_charset= 1;
 
615
    break;
 
616
  case (int) OPT_SKIP_OPTIMIZATION:
 
617
    extended_insert= opt_drop= quick= create_options=
 
618
      opt_disable_keys= opt_set_charset= 0;
 
619
    break;
 
620
  case (int) OPT_COMPACT:
 
621
  if (opt_compact)
 
622
  {
 
623
    opt_comments= opt_drop= opt_disable_keys= 0;
 
624
    opt_set_charset= 0;
 
625
  }
 
626
  case (int) OPT_TABLES:
 
627
    opt_databases=0;
 
628
    break;
 
629
  case (int) OPT_IGNORE_TABLE:
 
630
  {
 
631
    if (!strchr(argument, '.'))
 
632
    {
 
633
      fprintf(stderr, _("Illegal use of option --ignore-table=<database>.<table>\n"));
 
634
      exit(1);
 
635
    }
 
636
    string tmpptr(argument);
 
637
    ignore_table.insert(tmpptr); 
 
638
    break;
 
639
  }
 
640
  case (int) OPT_COMPATIBLE:
 
641
    {
 
642
      char buff[255];
 
643
      char *end= compatible_mode_normal_str;
 
644
      uint32_t i;
 
645
      uint32_t mode;
 
646
      uint32_t error_len;
 
647
 
 
648
      opt_quoted= 1;
 
649
      opt_set_charset= 0;
 
650
      opt_compatible_mode_str= argument;
 
651
      opt_compatible_mode= find_set(&compatible_mode_typelib,
 
652
                                    argument, strlen(argument),
 
653
                                    &err_ptr, &error_len);
 
654
      if (error_len)
 
655
      {
 
656
        strncpy(buff, err_ptr, min((uint32_t)sizeof(buff), error_len+1));
 
657
        fprintf(stderr, _("Invalid mode to --compatible: %s\n"), buff);
 
658
        exit(1);
 
659
      }
 
660
      mode= opt_compatible_mode;
 
661
      for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++)
 
662
      {
 
663
        if (mode & 1)
 
664
        {
 
665
          uint32_t len = strlen(compatible_mode_names[i]);
 
666
          end= strcpy(end, compatible_mode_names[i]) + len;
 
667
          end= strcpy(end, ",")+1;
 
668
        }
 
669
      }
 
670
      if (end!=compatible_mode_normal_str)
 
671
        end[-1]= 0;
 
672
    }
 
673
  }
 
674
  return 0;
 
675
}
 
676
 
 
677
static int get_options(int *argc, char ***argv)
 
678
{
 
679
  int ho_error;
 
680
 
 
681
  md_result_file= stdout;
 
682
  load_defaults("drizzle",load_default_groups,argc,argv);
 
683
  defaults_argv= *argv;
 
684
 
 
685
  if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
 
686
    return(ho_error);
 
687
 
 
688
  if (debug_info_flag)
 
689
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
 
690
  if (debug_check_flag)
 
691
    my_end_arg= MY_CHECK_ERROR;
 
692
 
 
693
  if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
 
694
                fields_terminated))
 
695
  {
 
696
    fprintf(stderr,
 
697
            _("%s: You must use option --tab with --fields-...\n"), my_progname);
 
698
    return(EX_USAGE);
 
699
  }
 
700
 
297
701
  if (opt_single_transaction && opt_lock_all_tables)
298
702
  {
299
703
    fprintf(stderr, _("%s: You can't use --single-transaction and "
300
 
                      "--lock-all-tables at the same time.\n"), progname.c_str());
301
 
    return(EX_USAGE);
302
 
  }
303
 
  if ((opt_databases || opt_alldbs) && ! path.empty())
 
704
            "--lock-all-tables at the same time.\n"), my_progname);
 
705
    return(EX_USAGE);
 
706
  }
 
707
  if (enclosed && opt_enclosed)
 
708
  {
 
709
    fprintf(stderr, _("%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n"), my_progname);
 
710
    return(EX_USAGE);
 
711
  }
 
712
  if ((opt_databases || opt_alldbs) && path)
304
713
  {
305
714
    fprintf(stderr,
306
715
            _("%s: --databases or --all-databases can't be used with --tab.\n"),
307
 
            progname.c_str());
 
716
            my_progname);
308
717
    return(EX_USAGE);
309
718
  }
310
 
 
 
719
  if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
 
720
  {
 
721
    short_usage();
 
722
    return EX_USAGE;
 
723
  }
311
724
  if (tty_password)
312
725
    opt_password=client_get_tty_password(NULL);
313
726
  return(0);
315
728
 
316
729
 
317
730
/*
 
731
** DB_error -- prints DRIZZLE error message and exits the program.
 
732
*/
 
733
static void DB_error(drizzle_result_st *res, drizzle_return_t ret,
 
734
                     const char *when)
 
735
{
 
736
  if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
737
  {
 
738
    maybe_die(EX_DRIZZLEERR, _("Got error: %s (%d) %s"),
 
739
              drizzle_result_error(res),
 
740
              drizzle_result_error_code(res),
 
741
              when);
 
742
    drizzle_result_free(res);
 
743
  }
 
744
  else
 
745
    maybe_die(EX_DRIZZLEERR, _("Got error: %d %s"), ret, when);
 
746
 
 
747
  return;
 
748
}
 
749
 
 
750
 
 
751
 
 
752
/*
318
753
  Prints out an error message and kills the process.
319
754
 
320
755
  SYNOPSIS
321
 
  die()
322
 
  error_num   - process return value
323
 
  fmt_reason  - a format string for use by vsnprintf.
324
 
  ...         - variable arguments for above fmt_reason string
 
756
    die()
 
757
    error_num   - process return value
 
758
    fmt_reason  - a format string for use by vsnprintf.
 
759
    ...         - variable arguments for above fmt_reason string
325
760
 
326
761
  DESCRIPTION
327
 
  This call prints out the formatted error message to stderr and then
328
 
  terminates the process.
 
762
    This call prints out the formatted error message to stderr and then
 
763
    terminates the process.
329
764
*/
330
765
static void die(int error_num, const char* fmt_reason, ...)
331
766
{
335
770
  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
336
771
  va_end(args);
337
772
 
338
 
  fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
 
773
  fprintf(stderr, "%s: %s\n", my_progname, buffer);
339
774
  fflush(stderr);
340
775
 
341
776
  ignore_errors= 0; /* force the exit */
342
777
  maybe_exit(error_num);
343
778
}
344
779
 
 
780
 
 
781
/*
 
782
  Prints out an error message and maybe kills the process.
 
783
 
 
784
  SYNOPSIS
 
785
    maybe_die()
 
786
    error_num   - process return value
 
787
    fmt_reason  - a format string for use by vsnprintf.
 
788
    ...         - variable arguments for above fmt_reason string
 
789
 
 
790
  DESCRIPTION
 
791
    This call prints out the formatted error message to stderr and then
 
792
    terminates the process, unless the --force command line option is used.
 
793
 
 
794
    This call should be used for non-fatal errors (such as database
 
795
    errors) that the code may still be able to continue to the next unit
 
796
    of work.
 
797
 
 
798
*/
 
799
static void maybe_die(int error_num, const char* fmt_reason, ...)
 
800
{
 
801
  char buffer[1000];
 
802
  va_list args;
 
803
  va_start(args,fmt_reason);
 
804
  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
 
805
  va_end(args);
 
806
 
 
807
  fprintf(stderr, "%s: %s\n", my_progname, buffer);
 
808
  fflush(stderr);
 
809
 
 
810
  maybe_exit(error_num);
 
811
}
 
812
 
 
813
 
 
814
 
 
815
/*
 
816
  Sends a query to server, optionally reads result, prints error message if
 
817
  some.
 
818
 
 
819
  SYNOPSIS
 
820
    drizzleclient_query_with_error_report()
 
821
    drizzle_con       connection to use
 
822
    res             if non zero, result will be put there with
 
823
                    drizzleclient_store_result()
 
824
    query           query to send to server
 
825
 
 
826
  RETURN VALUES
 
827
    0               query sending and (if res!=0) result reading went ok
 
828
    1               error
 
829
*/
 
830
 
 
831
static int drizzleclient_query_with_error_report(drizzle_con_st *con,
 
832
                                                 drizzle_result_st *result,
 
833
                                                 const char *query_str,
 
834
                                                 bool no_buffer)
 
835
{
 
836
  drizzle_return_t ret;
 
837
 
 
838
  if (drizzle_query_str(con, result, query_str, &ret) == NULL ||
 
839
      ret != DRIZZLE_RETURN_OK)
 
840
  {
 
841
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
842
    {
 
843
      maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
844
                query_str, drizzle_result_error(result),
 
845
                drizzle_result_error_code(result));
 
846
      drizzle_result_free(result);
 
847
    }
 
848
    else
 
849
    {
 
850
      maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
851
                query_str, drizzle_con_error(con), ret);
 
852
    }
 
853
    return 1;
 
854
  }
 
855
 
 
856
  if (no_buffer)
 
857
    ret= drizzle_column_buffer(result);
 
858
  else
 
859
    ret= drizzle_result_buffer(result);
 
860
  if (ret != DRIZZLE_RETURN_OK)
 
861
  {
 
862
    drizzle_result_free(result);
 
863
    maybe_die(EX_DRIZZLEERR, _("Couldn't execute '%s': %s (%d)"),
 
864
              query_str, drizzle_con_error(con), ret);
 
865
    return 1;
 
866
  }
 
867
 
 
868
  return 0;
 
869
}
 
870
 
 
871
/*
 
872
  Open a new .sql file to dump the table or view into
 
873
 
 
874
  SYNOPSIS
 
875
    open_sql_file_for_table
 
876
    name      name of the table or view
 
877
 
 
878
  RETURN VALUES
 
879
    0        Failed to open file
 
880
    > 0      Handle of the open file
 
881
*/
 
882
static FILE* open_sql_file_for_table(const char* table)
 
883
{
 
884
  FILE* res;
 
885
  char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
886
  convert_dirname(tmp_path,path,NULL);
 
887
  res= fopen(fn_format(filename, table, tmp_path, ".sql", 4), "w");
 
888
 
 
889
  return res;
 
890
}
 
891
 
 
892
 
345
893
static void free_resources(void)
346
894
{
347
895
  if (md_result_file && md_result_file != stdout)
348
896
    fclose(md_result_file);
349
 
  opt_password.erase();
 
897
  free(opt_password);
 
898
  if (defaults_argv)
 
899
    free_defaults(defaults_argv);
 
900
  my_end(my_end_arg);
350
901
}
351
902
 
352
903
 
353
 
void maybe_exit(int error)
 
904
static void maybe_exit(int error)
354
905
{
355
906
  if (!first_error)
356
907
    first_error= error;
357
908
  if (ignore_errors)
358
909
    return;
359
 
  delete db_connection;
360
 
  delete destination_connection;
 
910
  drizzle_con_free(&dcon);
 
911
  drizzle_free(&drizzle);
361
912
  free_resources();
362
913
  exit(error);
363
914
}
364
915
 
 
916
 
 
917
/*
 
918
  db_connect -- connects to the host and selects DB.
 
919
*/
 
920
 
 
921
static int connect_to_db(char *host, char *user,char *passwd)
 
922
{
 
923
  drizzle_return_t ret;
 
924
 
 
925
  verbose_msg(_("-- Connecting to %s...\n"), host ? host : "localhost");
 
926
  drizzle_create(&drizzle);
 
927
  drizzle_con_create(&drizzle, &dcon);
 
928
  drizzle_con_set_tcp(&dcon, host, opt_drizzle_port);
 
929
  drizzle_con_set_auth(&dcon, user, passwd);
 
930
  ret= drizzle_con_connect(&dcon);
 
931
  if (ret != DRIZZLE_RETURN_OK)
 
932
  {
 
933
    DB_error(NULL, ret, "when trying to connect");
 
934
    return(1);
 
935
  }
 
936
 
 
937
  return(0);
 
938
} /* connect_to_db */
 
939
 
 
940
 
 
941
/*
 
942
** dbDisconnect -- disconnects from the host.
 
943
*/
 
944
static void dbDisconnect(char *host)
 
945
{
 
946
  verbose_msg(_("-- Disconnecting from %s...\n"), host ? host : "localhost");
 
947
  drizzle_con_free(&dcon);
 
948
  drizzle_free(&drizzle);
 
949
} /* dbDisconnect */
 
950
 
 
951
 
 
952
static void unescape(FILE *file,char *pos,uint32_t length)
 
953
{
 
954
  char *tmp;
 
955
 
 
956
  if (!(tmp=(char*) malloc(length*2+1)))
 
957
    die(EX_DRIZZLEERR, _("Couldn't allocate memory"));
 
958
 
 
959
  drizzle_escape_string(tmp, pos, length);
 
960
  fputc('\'', file);
 
961
  fputs(tmp, file);
 
962
  fputc('\'', file);
 
963
  check_io(file);
 
964
  free(tmp);
 
965
  return;
 
966
} /* unescape */
 
967
 
 
968
 
 
969
static bool test_if_special_chars(const char *str)
 
970
{
 
971
  for ( ; *str ; str++)
 
972
    if (!my_isvar(charset_info,*str) && *str != '$')
 
973
      return 1;
 
974
  return 0;
 
975
} /* test_if_special_chars */
 
976
 
 
977
 
 
978
 
 
979
/*
 
980
  quote_name(name, buff, force)
 
981
 
 
982
  Quotes char string, taking into account compatible mode
 
983
 
 
984
  Args
 
985
 
 
986
  name                 Unquoted string containing that which will be quoted
 
987
  buff                 The buffer that contains the quoted value, also returned
 
988
  force                Flag to make it ignore 'test_if_special_chars'
 
989
 
 
990
  Returns
 
991
 
 
992
  buff                 quoted string
 
993
 
 
994
*/
 
995
static char *quote_name(const char *name, char *buff, bool force)
 
996
{
 
997
  char *to= buff;
 
998
  char qtype= '`';
 
999
 
 
1000
  if (!force && !opt_quoted && !test_if_special_chars(name))
 
1001
    return (char*) name;
 
1002
  *to++= qtype;
 
1003
  while (*name)
 
1004
  {
 
1005
    if (*name == qtype)
 
1006
      *to++= qtype;
 
1007
    *to++= *name++;
 
1008
  }
 
1009
  to[0]= qtype;
 
1010
  to[1]= 0;
 
1011
  return buff;
 
1012
} /* quote_name */
 
1013
 
 
1014
 
 
1015
/*
 
1016
  Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
 
1017
 
 
1018
  SYNOPSIS
 
1019
    quote_for_like()
 
1020
    name     name of the table
 
1021
    buff     quoted name of the table
 
1022
 
 
1023
  DESCRIPTION
 
1024
    Quote \, _, ' and % characters
 
1025
 
 
1026
    Note: Because DRIZZLE uses the C escape syntax in strings
 
1027
    (for example, '\n' to represent newline), you must double
 
1028
    any '\' that you use in your LIKE  strings. For example, to
 
1029
    search for '\n', specify it as '\\n'. To search for '\', specify
 
1030
    it as '\\\\' (the backslashes are stripped once by the parser
 
1031
    and another time when the pattern match is done, leaving a
 
1032
    single backslash to be matched).
 
1033
 
 
1034
    Example: "t\1" => "t\\\\1"
 
1035
 
 
1036
*/
 
1037
static char *quote_for_like(const char *name, char *buff)
 
1038
{
 
1039
  char *to= buff;
 
1040
  *to++= '\'';
 
1041
  while (*name)
 
1042
  {
 
1043
    if (*name == '\\')
 
1044
    {
 
1045
      *to++='\\';
 
1046
      *to++='\\';
 
1047
      *to++='\\';
 
1048
    }
 
1049
    else if (*name == '\'' || *name == '_'  || *name == '%')
 
1050
      *to++= '\\';
 
1051
    *to++= *name++;
 
1052
  }
 
1053
  to[0]= '\'';
 
1054
  to[1]= 0;
 
1055
  return buff;
 
1056
}
 
1057
 
 
1058
 
 
1059
/*
 
1060
  Quote and print a string.
 
1061
 
 
1062
  SYNOPSIS
 
1063
    print_quoted_xml()
 
1064
    xml_file    - output file
 
1065
    str         - string to print
 
1066
    len         - its length
 
1067
 
 
1068
  DESCRIPTION
 
1069
    Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
 
1070
*/
 
1071
 
 
1072
static void print_quoted_xml(FILE *xml_file, const char *str, uint32_t len)
 
1073
{
 
1074
  const char *end;
 
1075
 
 
1076
  for (end= str + len; str != end; str++)
 
1077
  {
 
1078
    switch (*str) {
 
1079
    case '<':
 
1080
      fputs("&lt;", xml_file);
 
1081
      break;
 
1082
    case '>':
 
1083
      fputs("&gt;", xml_file);
 
1084
      break;
 
1085
    case '&':
 
1086
      fputs("&amp;", xml_file);
 
1087
      break;
 
1088
    case '\"':
 
1089
      fputs("&quot;", xml_file);
 
1090
      break;
 
1091
    default:
 
1092
      fputc(*str, xml_file);
 
1093
      break;
 
1094
    }
 
1095
  }
 
1096
  check_io(xml_file);
 
1097
}
 
1098
 
 
1099
 
 
1100
/*
 
1101
  Print xml tag. Optionally add attribute(s).
 
1102
 
 
1103
  SYNOPSIS
 
1104
    print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
 
1105
                    ..., attribute_name_n, attribute_value_n, NULL)
 
1106
    xml_file              - output file
 
1107
    sbeg                  - line beginning
 
1108
    line_end              - line ending
 
1109
    tag_name              - XML tag name.
 
1110
    first_attribute_name  - tag and first attribute
 
1111
    first_attribute_value - (Implied) value of first attribute
 
1112
    attribute_name_n      - attribute n
 
1113
    attribute_value_n     - value of attribute n
 
1114
 
 
1115
  DESCRIPTION
 
1116
    Print XML tag with any number of attribute="value" pairs to the xml_file.
 
1117
 
 
1118
    Format is:
 
1119
      sbeg<tag_name first_attribute_name="first_attribute_value" ...
 
1120
      attribute_name_n="attribute_value_n">send
 
1121
  NOTE
 
1122
    Additional arguments must be present in attribute/value pairs.
 
1123
    The last argument should be the null character pointer.
 
1124
    All attribute_value arguments MUST be NULL terminated strings.
 
1125
    All attribute_value arguments will be quoted before output.
 
1126
*/
 
1127
 
 
1128
static void print_xml_tag(FILE * xml_file, const char* sbeg,
 
1129
                          const char* line_end,
 
1130
                          const char* tag_name,
 
1131
                          const char* first_attribute_name, ...)
 
1132
{
 
1133
  va_list arg_list;
 
1134
  const char *attribute_name, *attribute_value;
 
1135
 
 
1136
  fputs(sbeg, xml_file);
 
1137
  fputc('<', xml_file);
 
1138
  fputs(tag_name, xml_file);
 
1139
 
 
1140
  va_start(arg_list, first_attribute_name);
 
1141
  attribute_name= first_attribute_name;
 
1142
  while (attribute_name != NULL)
 
1143
  {
 
1144
    attribute_value= va_arg(arg_list, char *);
 
1145
    assert(attribute_value != NULL);
 
1146
 
 
1147
    fputc(' ', xml_file);
 
1148
    fputs(attribute_name, xml_file);
 
1149
    fputc('\"', xml_file);
 
1150
 
 
1151
    print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
 
1152
    fputc('\"', xml_file);
 
1153
 
 
1154
    attribute_name= va_arg(arg_list, char *);
 
1155
  }
 
1156
  va_end(arg_list);
 
1157
 
 
1158
  fputc('>', xml_file);
 
1159
  fputs(line_end, xml_file);
 
1160
  check_io(xml_file);
 
1161
}
 
1162
 
 
1163
 
 
1164
/*
 
1165
  Print xml tag with for a field that is null
 
1166
 
 
1167
  SYNOPSIS
 
1168
    print_xml_null_tag()
 
1169
    xml_file    - output file
 
1170
    sbeg        - line beginning
 
1171
    stag_atr    - tag and attribute
 
1172
    sval        - value of attribute
 
1173
    line_end        - line ending
 
1174
 
 
1175
  DESCRIPTION
 
1176
    Print tag with one attribute to the xml_file. Format is:
 
1177
      <stag_atr="sval" xsi:nil="true"/>
 
1178
  NOTE
 
1179
    sval MUST be a NULL terminated string.
 
1180
    sval string will be qouted before output.
 
1181
*/
 
1182
 
 
1183
static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
 
1184
                               const char* stag_atr, const char* sval,
 
1185
                               const char* line_end)
 
1186
{
 
1187
  fputs(sbeg, xml_file);
 
1188
  fputs("<", xml_file);
 
1189
  fputs(stag_atr, xml_file);
 
1190
  fputs("\"", xml_file);
 
1191
  print_quoted_xml(xml_file, sval, strlen(sval));
 
1192
  fputs("\" xsi:nil=\"true\" />", xml_file);
 
1193
  fputs(line_end, xml_file);
 
1194
  check_io(xml_file);
 
1195
}
 
1196
 
 
1197
 
 
1198
/*
 
1199
  Print xml tag with many attributes.
 
1200
 
 
1201
  SYNOPSIS
 
1202
    print_xml_row()
 
1203
    xml_file    - output file
 
1204
    row_name    - xml tag name
 
1205
    tableRes    - query result
 
1206
    row         - result row
 
1207
 
 
1208
  DESCRIPTION
 
1209
    Print tag with many attribute to the xml_file. Format is:
 
1210
      \t\t<row_name Atr1="Val1" Atr2="Val2"... />
 
1211
  NOTE
 
1212
    All atributes and values will be quoted before output.
 
1213
*/
 
1214
 
 
1215
static void print_xml_row(FILE *xml_file, const char *row_name,
 
1216
                          drizzle_result_st *tableRes, drizzle_row_t *row)
 
1217
{
 
1218
  uint32_t i;
 
1219
  drizzle_column_st *column;
 
1220
  size_t *lengths= drizzle_row_field_sizes(tableRes);
 
1221
 
 
1222
  fprintf(xml_file, "\t\t<%s", row_name);
 
1223
  check_io(xml_file);
 
1224
  drizzle_column_seek(tableRes, 0);
 
1225
  for (i= 0; (column= drizzle_column_next(tableRes)); i++)
 
1226
  {
 
1227
    if ((*row)[i])
 
1228
    {
 
1229
      fputc(' ', xml_file);
 
1230
      print_quoted_xml(xml_file, drizzle_column_name(column),
 
1231
                       strlen(drizzle_column_name(column)));
 
1232
      fputs("=\"", xml_file);
 
1233
      print_quoted_xml(xml_file, (*row)[i], lengths[i]);
 
1234
      fputc('"', xml_file);
 
1235
      check_io(xml_file);
 
1236
    }
 
1237
  }
 
1238
  fputs(" />\n", xml_file);
 
1239
  check_io(xml_file);
 
1240
}
 
1241
 
 
1242
 
 
1243
/*
 
1244
  Print hex value for blob data.
 
1245
 
 
1246
  SYNOPSIS
 
1247
    print_blob_as_hex()
 
1248
    output_file         - output file
 
1249
    str                 - string to print
 
1250
    len                 - its length
 
1251
 
 
1252
  DESCRIPTION
 
1253
    Print hex value for blob data.
 
1254
*/
 
1255
 
 
1256
static void print_blob_as_hex(FILE *output_file, const char *str, uint32_t len)
 
1257
{
 
1258
    /* sakaik got the idea to to provide blob's in hex notation. */
 
1259
    const char *ptr= str, *end= ptr + len;
 
1260
    for (; ptr < end ; ptr++)
 
1261
      fprintf(output_file, "%02X", *((unsigned char *)ptr));
 
1262
    check_io(output_file);
 
1263
}
 
1264
 
 
1265
/*
 
1266
  get_table_structure -- retrievs database structure, prints out corresponding
 
1267
  CREATE statement and fills out insert_pat if the table is the type we will
 
1268
  be dumping.
 
1269
 
 
1270
  ARGS
 
1271
    table       - table name
 
1272
    db          - db name
 
1273
    table_type  - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
 
1274
    ignore_flag - what we must particularly ignore - see IGNORE_ defines above
 
1275
    num_fields  - number of fields in the table
 
1276
 
 
1277
  RETURN
 
1278
    true if success, false if error
 
1279
*/
 
1280
 
 
1281
static bool get_table_structure(char *table, char *db, char *table_type,
 
1282
                                char *ignore_flag, uint64_t *num_fields)
 
1283
{
 
1284
  bool    init=0, delayed, write_data, complete_insert;
 
1285
  char       *result_table, *opt_quoted_table;
 
1286
  const char *insert_option;
 
1287
  char       name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE+3];
 
1288
  char       table_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+3];
 
1289
  char       table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3];
 
1290
  char       query_buff[QUERY_LENGTH];
 
1291
  FILE       *sql_file= md_result_file;
 
1292
  drizzle_result_st result;
 
1293
  drizzle_row_t  row;
 
1294
 
 
1295
  *ignore_flag= check_if_ignore_table(table, table_type);
 
1296
 
 
1297
  delayed= opt_delayed;
 
1298
  if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
 
1299
  {
 
1300
    delayed= 0;
 
1301
    verbose_msg(_("-- Warning: Unable to use delayed inserts for table '%s' "
 
1302
                "because it's of type %s\n"), table, table_type);
 
1303
  }
 
1304
 
 
1305
  complete_insert= 0;
 
1306
  if ((write_data= !(*ignore_flag & IGNORE_DATA)))
 
1307
  {
 
1308
    complete_insert= opt_complete_insert;
 
1309
    insert_pat.clear();
 
1310
  }
 
1311
 
 
1312
  insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
 
1313
                  delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
 
1314
 
 
1315
  verbose_msg(_("-- Retrieving table structure for table %s...\n"), table);
 
1316
 
 
1317
  result_table=     quote_name(table, table_buff, 1);
 
1318
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
1319
 
 
1320
  if (opt_order_by_primary)
 
1321
  {
 
1322
    free(order_by);
 
1323
    order_by= primary_key_fields(result_table);
 
1324
  }
 
1325
 
 
1326
  if (!opt_xml)
 
1327
  {
 
1328
    /* using SHOW CREATE statement */
 
1329
    if (!opt_no_create_info)
 
1330
    {
 
1331
      /* Make an sql-file, if path was given iow. option -T was given */
 
1332
      char buff[20+FN_REFLEN];
 
1333
      const drizzle_column_st *column;
 
1334
 
 
1335
      snprintf(buff, sizeof(buff), "show create table %s", result_table);
 
1336
 
 
1337
      if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
1338
        return false;
 
1339
 
 
1340
      if (path)
 
1341
      {
 
1342
        if (!(sql_file= open_sql_file_for_table(table)))
 
1343
        {
 
1344
          drizzle_result_free(&result);
 
1345
          return false;
 
1346
        }
 
1347
 
 
1348
        write_header(sql_file, db);
 
1349
      }
 
1350
      if (!opt_xml && opt_comments)
 
1351
      {
 
1352
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
1353
                result_table);
 
1354
        check_io(sql_file);
 
1355
      }
 
1356
      if (opt_drop)
 
1357
      {
 
1358
      /*
 
1359
        Even if the "table" is a view, we do a DROP TABLE here.
 
1360
       */
 
1361
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
 
1362
        check_io(sql_file);
 
1363
      }
 
1364
 
 
1365
      column= drizzle_column_index(&result, 0);
 
1366
 
 
1367
      row= drizzle_row_next(&result);
 
1368
 
 
1369
      fprintf(sql_file, "%s;\n", row[1]);
 
1370
 
 
1371
      check_io(sql_file);
 
1372
      drizzle_result_free(&result);
 
1373
    }
 
1374
 
 
1375
    snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
1376
             result_table);
 
1377
 
 
1378
    if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
 
1379
    {
 
1380
      if (path)
 
1381
        fclose(sql_file);
 
1382
      return false;
 
1383
    }
 
1384
 
 
1385
    /*
 
1386
      If write_data is true, then we build up insert statements for
 
1387
      the table's data. Note: in subsequent lines of code, this test
 
1388
      will have to be performed each time we are appending to
 
1389
      insert_pat.
 
1390
    */
 
1391
    if (write_data)
 
1392
    {
 
1393
      if (opt_replace_into)
 
1394
        insert_pat.append("REPLACE ");
 
1395
      else
 
1396
        insert_pat.append("INSERT ");
 
1397
      insert_pat.append(insert_option);
 
1398
      insert_pat.append("INTO ");
 
1399
      insert_pat.append(opt_quoted_table);
 
1400
      if (complete_insert)
 
1401
      {
 
1402
        insert_pat.append(" (");
 
1403
      }
 
1404
      else
 
1405
      {
 
1406
        insert_pat.append(" VALUES ");
 
1407
        if (!extended_insert)
 
1408
          insert_pat.append("(");
 
1409
      }
 
1410
    }
 
1411
 
 
1412
    while ((row= drizzle_row_next(&result)))
 
1413
    {
 
1414
      if (complete_insert)
 
1415
      {
 
1416
        if (init)
 
1417
        {
 
1418
          insert_pat.append(", ");
 
1419
        }
 
1420
        init=1;
 
1421
        insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
1422
      }
 
1423
    }
 
1424
    *num_fields= drizzle_result_row_count(&result);
 
1425
    drizzle_result_free(&result);
 
1426
  }
 
1427
  else
 
1428
  {
 
1429
    verbose_msg(_("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n"),
 
1430
                my_progname, drizzle_con_error(&dcon));
 
1431
 
 
1432
    snprintf(query_buff, sizeof(query_buff), "show fields from %s",
 
1433
             result_table);
 
1434
    if (drizzleclient_query_with_error_report(&dcon, &result, query_buff, false))
 
1435
      return false;
 
1436
 
 
1437
    /* Make an sql-file, if path was given iow. option -T was given */
 
1438
    if (!opt_no_create_info)
 
1439
    {
 
1440
      if (path)
 
1441
      {
 
1442
        if (!(sql_file= open_sql_file_for_table(table)))
 
1443
        {
 
1444
          drizzle_result_free(&result);
 
1445
          return false;
 
1446
        }
 
1447
        write_header(sql_file, db);
 
1448
      }
 
1449
      if (!opt_xml && opt_comments)
 
1450
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
 
1451
                result_table);
 
1452
      if (opt_drop)
 
1453
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
 
1454
      if (!opt_xml)
 
1455
        fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
 
1456
      else
 
1457
        print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
 
1458
                NULL);
 
1459
      check_io(sql_file);
 
1460
    }
 
1461
 
 
1462
    if (write_data)
 
1463
    {
 
1464
      if (opt_replace_into)
 
1465
        insert_pat.append("REPLACE ");
 
1466
      else
 
1467
        insert_pat.append("INSERT ");
 
1468
      insert_pat.append(insert_option);
 
1469
      insert_pat.append("INTO ");
 
1470
      insert_pat.append(result_table);
 
1471
      if (complete_insert)
 
1472
        insert_pat.append(" (");
 
1473
      else
 
1474
      {
 
1475
        insert_pat.append(" VALUES ");
 
1476
        if (!extended_insert)
 
1477
          insert_pat.append("(");
 
1478
      }
 
1479
    }
 
1480
 
 
1481
    while ((row= drizzle_row_next(&result)))
 
1482
    {
 
1483
      size_t *lengths= drizzle_row_field_sizes(&result);
 
1484
      if (init)
 
1485
      {
 
1486
        if (!opt_xml && !opt_no_create_info)
 
1487
        {
 
1488
          fputs(",\n",sql_file);
 
1489
          check_io(sql_file);
 
1490
        }
 
1491
        if (complete_insert)
 
1492
          insert_pat.append(", ");
 
1493
      }
 
1494
      init=1;
 
1495
      if (complete_insert)
 
1496
        insert_pat.append(quote_name(row[SHOW_FIELDNAME], name_buff, 0));
 
1497
      if (!opt_no_create_info)
 
1498
      {
 
1499
        if (opt_xml)
 
1500
        {
 
1501
          print_xml_row(sql_file, "field", &result, &row);
 
1502
          continue;
 
1503
        }
 
1504
 
 
1505
        if (opt_keywords)
 
1506
          fprintf(sql_file, "  %s.%s %s", result_table,
 
1507
                  quote_name(row[SHOW_FIELDNAME],name_buff, 0),
 
1508
                  row[SHOW_TYPE]);
 
1509
        else
 
1510
          fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
 
1511
                                                  name_buff, 0),
 
1512
                  row[SHOW_TYPE]);
 
1513
        if (row[SHOW_DEFAULT])
 
1514
        {
 
1515
          fputs(" DEFAULT ", sql_file);
 
1516
          unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
 
1517
        }
 
1518
        if (!row[SHOW_NULL][0])
 
1519
          fputs(" NOT NULL", sql_file);
 
1520
        if (row[SHOW_EXTRA][0])
 
1521
          fprintf(sql_file, " %s",row[SHOW_EXTRA]);
 
1522
        check_io(sql_file);
 
1523
      }
 
1524
    }
 
1525
    *num_fields= drizzle_result_row_count(&result);
 
1526
    drizzle_result_free(&result);
 
1527
 
 
1528
    if (!opt_no_create_info)
 
1529
    {
 
1530
      /* Make an sql-file, if path was given iow. option -T was given */
 
1531
      char buff[20+FN_REFLEN];
 
1532
      uint32_t keynr,primary_key;
 
1533
      snprintf(buff, sizeof(buff), "show keys from %s", result_table);
 
1534
      if (drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
1535
      {
 
1536
        fprintf(stderr, _("%s: Can't get keys for table %s\n"),
 
1537
                my_progname, result_table);
 
1538
        if (path)
 
1539
          fclose(sql_file);
 
1540
        return false;
 
1541
      }
 
1542
 
 
1543
      /* Find first which key is primary key */
 
1544
      keynr=0;
 
1545
      primary_key=INT_MAX;
 
1546
      while ((row= drizzle_row_next(&result)))
 
1547
      {
 
1548
        if (atoi(row[3]) == 1)
 
1549
        {
 
1550
          keynr++;
 
1551
#ifdef FORCE_PRIMARY_KEY
 
1552
          if (atoi(row[1]) == 0 && primary_key == INT_MAX)
 
1553
            primary_key=keynr;
 
1554
#endif
 
1555
          if (!strcmp(row[2],"PRIMARY"))
 
1556
          {
 
1557
            primary_key=keynr;
 
1558
            break;
 
1559
          }
 
1560
        }
 
1561
      }
 
1562
      drizzle_row_seek(&result,0);
 
1563
      keynr=0;
 
1564
      while ((row= drizzle_row_next(&result)))
 
1565
      {
 
1566
        if (opt_xml)
 
1567
        {
 
1568
          print_xml_row(sql_file, "key", &result, &row);
 
1569
          continue;
 
1570
        }
 
1571
 
 
1572
        if (atoi(row[3]) == 1)
 
1573
        {
 
1574
          if (keynr++)
 
1575
            putc(')', sql_file);
 
1576
          if (atoi(row[1]))       /* Test if duplicate key */
 
1577
            /* Duplicate allowed */
 
1578
            fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff,0));
 
1579
          else if (keynr == primary_key)
 
1580
            fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
 
1581
          else
 
1582
            fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff,
 
1583
                                                            0));
 
1584
        }
 
1585
        else
 
1586
          putc(',', sql_file);
 
1587
        fputs(quote_name(row[4], name_buff, 0), sql_file);
 
1588
        if (row[7])
 
1589
          fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
 
1590
        check_io(sql_file);
 
1591
      }
 
1592
      drizzle_result_free(&result);
 
1593
      if (!opt_xml)
 
1594
      {
 
1595
        if (keynr)
 
1596
          putc(')', sql_file);
 
1597
        fputs("\n)",sql_file);
 
1598
        check_io(sql_file);
 
1599
      }
 
1600
      /* Get DRIZZLE specific create options */
 
1601
      if (create_options)
 
1602
      {
 
1603
        char show_name_buff[DRIZZLE_MAX_COLUMN_NAME_SIZE*2+2+24];
 
1604
 
 
1605
        /* Check memory for quote_for_like() */
 
1606
        snprintf(buff, sizeof(buff), "show table status like %s",
 
1607
                 quote_for_like(table, show_name_buff));
 
1608
 
 
1609
        if (!drizzleclient_query_with_error_report(&dcon, &result, buff, false))
 
1610
        {
 
1611
          if (!(row= drizzle_row_next(&result)))
 
1612
          {
 
1613
            fprintf(stderr,
 
1614
                    _("Error: Couldn't read status information for table %s\n"),
 
1615
                    result_table);
 
1616
          }
 
1617
          else
 
1618
          {
 
1619
            if (opt_xml)
 
1620
              print_xml_row(sql_file, "options", &result, &row);
 
1621
            else
 
1622
            {
 
1623
              fputs("/*!",sql_file);
 
1624
              print_value(sql_file,&result,row,"engine=","Engine",0);
 
1625
              print_value(sql_file,&result,row,"","Create_options",0);
 
1626
              print_value(sql_file,&result,row,"comment=","Comment",1);
 
1627
 
 
1628
              fputs(" */",sql_file);
 
1629
              check_io(sql_file);
 
1630
            }
 
1631
          }
 
1632
          drizzle_result_free(&result);
 
1633
        }
 
1634
      }
 
1635
      if (!opt_xml)
 
1636
        fputs(";\n", sql_file);
 
1637
      else
 
1638
        fputs("\t</table_structure>\n", sql_file);
 
1639
      check_io(sql_file);
 
1640
    }
 
1641
  }
 
1642
  if (complete_insert) {
 
1643
    insert_pat.append(") VALUES ");
 
1644
    if (!extended_insert)
 
1645
      insert_pat.append("(");
 
1646
  }
 
1647
  if (sql_file != md_result_file)
 
1648
  {
 
1649
    fputs("\n", sql_file);
 
1650
    write_footer(sql_file);
 
1651
    fclose(sql_file);
 
1652
  }
 
1653
  return true;
 
1654
} /* get_table_structure */
 
1655
 
 
1656
static void add_load_option(string &str, const char *option,
 
1657
                            const char *option_value)
 
1658
{
 
1659
  if (!option_value)
 
1660
  {
 
1661
    /* Null value means we don't add this option. */
 
1662
    return;
 
1663
  }
 
1664
 
 
1665
  str.append(option);
 
1666
 
 
1667
  if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
 
1668
  {
 
1669
    /* It's a hex constant, don't escape */
 
1670
    str.append(option_value);
 
1671
  }
 
1672
  else
 
1673
  {
 
1674
    /* char constant; escape */
 
1675
    field_escape(str, option_value);
 
1676
  }
 
1677
}
 
1678
 
 
1679
 
 
1680
/*
 
1681
  Allow the user to specify field terminator strings like:
 
1682
  "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
 
1683
  This is done by doubling ' and add a end -\ if needed to avoid
 
1684
  syntax errors from the SQL parser.
 
1685
*/
 
1686
 
 
1687
static void field_escape(string &in, const char *from)
 
1688
{
 
1689
  uint32_t end_backslashes= 0;
 
1690
 
 
1691
  in.append("'");
 
1692
 
 
1693
  while (*from)
 
1694
  {
 
1695
    in.append(from, 1);
 
1696
 
 
1697
    if (*from == '\\')
 
1698
      end_backslashes^=1;    /* find odd number of backslashes */
 
1699
    else
 
1700
    {
 
1701
      if (*from == '\'' && !end_backslashes)
 
1702
      {
 
1703
        /* We want a duplicate of "'" for DRIZZLE */
 
1704
        in.append("\'");
 
1705
      }
 
1706
      end_backslashes=0;
 
1707
    }
 
1708
    from++;
 
1709
  }
 
1710
  /* Add missing backslashes if user has specified odd number of backs.*/
 
1711
  if (end_backslashes)
 
1712
    in.append("\\");
 
1713
 
 
1714
  in.append("'");
 
1715
}
 
1716
 
 
1717
 
 
1718
 
 
1719
/*
 
1720
 
 
1721
 SYNOPSIS
 
1722
  dump_table()
 
1723
 
 
1724
  dump_table saves database contents as a series of INSERT statements.
 
1725
 
 
1726
  ARGS
 
1727
   table - table name
 
1728
   db    - db name
 
1729
 
 
1730
   RETURNS
 
1731
    void
 
1732
*/
 
1733
 
 
1734
 
 
1735
static void dump_table(char *table, char *db)
 
1736
{
 
1737
  char ignore_flag;
 
1738
  char table_buff[DRIZZLE_MAX_TABLE_SIZE+3];
 
1739
  string query_string;
 
1740
  char table_type[DRIZZLE_MAX_TABLE_SIZE];
 
1741
  char *result_table, table_buff2[DRIZZLE_MAX_TABLE_SIZE*2+3], *opt_quoted_table;
 
1742
  int error= 0;
 
1743
  uint32_t rownr, row_break, total_length, init_length;
 
1744
  uint64_t num_fields= 0;
 
1745
  drizzle_return_t ret;
 
1746
  drizzle_result_st result;
 
1747
  drizzle_column_st *column;
 
1748
  drizzle_row_t row;
 
1749
 
 
1750
 
 
1751
  /*
 
1752
    Make sure you get the create table info before the following check for
 
1753
    --no-data flag below. Otherwise, the create table info won't be printed.
 
1754
  */
 
1755
  if (!get_table_structure(table, db, table_type, &ignore_flag, &num_fields))
 
1756
  {
 
1757
    maybe_die(EX_TABLE_STATUS, _("Error retrieving table structure for table: \"%s\""), table);
 
1758
    return;
 
1759
  }
 
1760
 
 
1761
  /* Check --no-data flag */
 
1762
  if (opt_no_data)
 
1763
  {
 
1764
    verbose_msg(_("-- Skipping dump data for table '%s', --no-data was used\n"),
 
1765
                table);
 
1766
    return;
 
1767
  }
 
1768
 
 
1769
  /*
 
1770
    If the table type is a merge table or any type that has to be
 
1771
     _completely_ ignored and no data dumped
 
1772
  */
 
1773
  if (ignore_flag & IGNORE_DATA)
 
1774
  {
 
1775
    verbose_msg(_("-- Warning: Skipping data for table '%s' because " \
 
1776
                "it's of type %s\n"), table, table_type);
 
1777
    return;
 
1778
  }
 
1779
  /* Check that there are any fields in the table */
 
1780
  if (num_fields == 0)
 
1781
  {
 
1782
    verbose_msg(_("-- Skipping dump data for table '%s', it has no fields\n"),
 
1783
                table);
 
1784
    return;
 
1785
  }
 
1786
 
 
1787
  result_table= quote_name(table,table_buff, 1);
 
1788
  opt_quoted_table= quote_name(table, table_buff2, 0);
 
1789
 
 
1790
  verbose_msg(_("-- Sending SELECT query...\n"));
 
1791
 
 
1792
  query_string.clear();
 
1793
  query_string.reserve(1024);
 
1794
 
 
1795
  if (path)
 
1796
  {
 
1797
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
 
1798
 
 
1799
    /*
 
1800
      Convert the path to native os format
 
1801
      and resolve to the full filepath.
 
1802
    */
 
1803
    convert_dirname(tmp_path,path,NULL);
 
1804
    my_load_path(tmp_path, tmp_path, NULL);
 
1805
    fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
 
1806
 
 
1807
    /* Must delete the file that 'INTO OUTFILE' will write to */
 
1808
    my_delete(filename, MYF(0));
 
1809
 
 
1810
    /* now build the query string */
 
1811
 
 
1812
    query_string.append( "SELECT * INTO OUTFILE '");
 
1813
    query_string.append( filename);
 
1814
    query_string.append( "'");
 
1815
 
 
1816
    if (fields_terminated || enclosed || opt_enclosed || escaped)
 
1817
      query_string.append( " FIELDS");
 
1818
 
 
1819
    add_load_option(query_string, " TERMINATED BY ", fields_terminated);
 
1820
    add_load_option(query_string, " ENCLOSED BY ", enclosed);
 
1821
    add_load_option(query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
 
1822
    add_load_option(query_string, " ESCAPED BY ", escaped);
 
1823
    add_load_option(query_string, " LINES TERMINATED BY ", lines_terminated);
 
1824
 
 
1825
    query_string.append( " FROM ");
 
1826
    query_string.append( result_table);
 
1827
 
 
1828
    if (where)
 
1829
    {
 
1830
      query_string.append( " WHERE ");
 
1831
      query_string.append( where);
 
1832
    }
 
1833
 
 
1834
    if (order_by)
 
1835
    {
 
1836
      query_string.append( " ORDER BY ");
 
1837
      query_string.append( order_by);
 
1838
    }
 
1839
 
 
1840
    if (drizzle_query(&dcon, &result, query_string.c_str(),
 
1841
                      query_string.length(), &ret) == NULL ||
 
1842
        ret != DRIZZLE_RETURN_OK)
 
1843
    {
 
1844
      DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
 
1845
 
 
1846
      return;
 
1847
    }
 
1848
    drizzle_result_free(&result);
 
1849
  }
 
1850
  else
 
1851
  {
 
1852
    if (!opt_xml && opt_comments)
 
1853
    {
 
1854
      fprintf(md_result_file,_("\n--\n-- Dumping data for table %s\n--\n"),
 
1855
              result_table);
 
1856
      check_io(md_result_file);
 
1857
    }
 
1858
 
 
1859
    query_string.append( "SELECT * FROM ");
 
1860
    query_string.append( result_table);
 
1861
 
 
1862
    if (where)
 
1863
    {
 
1864
      if (!opt_xml && opt_comments)
 
1865
      {
 
1866
        fprintf(md_result_file, "-- WHERE:  %s\n", where);
 
1867
        check_io(md_result_file);
 
1868
      }
 
1869
 
 
1870
      query_string.append( " WHERE ");
 
1871
      query_string.append( where);
 
1872
    }
 
1873
    if (order_by)
 
1874
    {
 
1875
      if (!opt_xml && opt_comments)
 
1876
      {
 
1877
        fprintf(md_result_file, "-- ORDER BY:  %s\n", order_by);
 
1878
        check_io(md_result_file);
 
1879
      }
 
1880
      query_string.append( " ORDER BY ");
 
1881
      query_string.append( order_by);
 
1882
    }
 
1883
 
 
1884
    if (!opt_xml && !opt_compact)
 
1885
    {
 
1886
      fputs("\n", md_result_file);
 
1887
      check_io(md_result_file);
 
1888
    }
 
1889
    if (drizzleclient_query_with_error_report(&dcon, &result,
 
1890
                                              query_string.c_str(), quick))
 
1891
    {
 
1892
      goto err;
 
1893
    }
 
1894
 
 
1895
    verbose_msg(_("-- Retrieving rows...\n"));
 
1896
    if (drizzle_result_column_count(&result) != num_fields)
 
1897
    {
 
1898
      fprintf(stderr,_("%s: Error in field count for table: %s !  Aborting.\n"),
 
1899
              my_progname, result_table);
 
1900
      error= EX_CONSCHECK;
 
1901
      drizzle_result_free(&result);
 
1902
      goto err;
 
1903
    }
 
1904
 
 
1905
    /* Moved disable keys to after lock per bug 15977 */
 
1906
    if (opt_disable_keys)
 
1907
    {
 
1908
      fprintf(md_result_file, "ALTER TABLE %s DISABLE KEYS;\n",
 
1909
              opt_quoted_table);
 
1910
      check_io(md_result_file);
 
1911
    }
 
1912
 
 
1913
    total_length= DRIZZLE_MAX_LINE_LENGTH;                /* Force row break */
 
1914
    row_break=0;
 
1915
    rownr=0;
 
1916
    init_length=(uint32_t) insert_pat.length()+4;
 
1917
    if (opt_xml)
 
1918
      print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
 
1919
              NULL);
 
1920
    if (opt_autocommit)
 
1921
    {
 
1922
      fprintf(md_result_file, "set autocommit=0;\n");
 
1923
      check_io(md_result_file);
 
1924
    }
 
1925
 
 
1926
    row= NULL;
 
1927
 
 
1928
    while (1)
 
1929
    {
 
1930
      uint32_t i;
 
1931
      size_t *lengths;
 
1932
 
 
1933
      if (quick)
 
1934
      {
 
1935
        if (row)
 
1936
          drizzle_row_free(&result, row);
 
1937
 
 
1938
        row= drizzle_row_buffer(&result, &ret);
 
1939
        if (ret != DRIZZLE_RETURN_OK)
 
1940
        {
 
1941
          fprintf(stderr,
 
1942
                _("%s: Error reading rows for table: %s (%d:%s) ! Aborting.\n"),
 
1943
                  my_progname, result_table, ret, drizzle_con_error(&dcon));
 
1944
          drizzle_result_free(&result);
 
1945
          goto err;
 
1946
        }
 
1947
      }
 
1948
      else
 
1949
        row= drizzle_row_next(&result);
 
1950
 
 
1951
      if (row == NULL)
 
1952
        break;
 
1953
 
 
1954
      lengths= drizzle_row_field_sizes(&result);
 
1955
 
 
1956
      rownr++;
 
1957
      if ((rownr % show_progress_size) == 0)
 
1958
      {
 
1959
        verbose_msg(_("-- %"PRIu32" of ~%"PRIu64" rows dumped for table %s\n"), rownr, total_rows, opt_quoted_table);
 
1960
      }
 
1961
      if (!extended_insert && !opt_xml)
 
1962
      {
 
1963
        fputs(insert_pat.c_str(),md_result_file);
 
1964
        check_io(md_result_file);
 
1965
      }
 
1966
      drizzle_column_seek(&result,0);
 
1967
 
 
1968
      if (opt_xml)
 
1969
      {
 
1970
        fputs("\t<row>\n", md_result_file);
 
1971
        check_io(md_result_file);
 
1972
      }
 
1973
 
 
1974
      for (i= 0; i < drizzle_result_column_count(&result); i++)
 
1975
      {
 
1976
        int is_blob;
 
1977
        uint32_t length= lengths[i];
 
1978
 
 
1979
        if (!(column= drizzle_column_next(&result)))
 
1980
          die(EX_CONSCHECK,
 
1981
                      _("Not enough fields from table %s! Aborting.\n"),
 
1982
                      result_table);
 
1983
 
 
1984
        /*
 
1985
           63 is my_charset_bin. If charsetnr is not 63,
 
1986
           we have not a BLOB but a TEXT column.
 
1987
           we'll dump in hex only BLOB columns.
 
1988
        */
 
1989
        is_blob= (opt_hex_blob && drizzle_column_charset(column) == 63 &&
 
1990
                  (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_VARCHAR ||
 
1991
                   drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_BLOB)) ? 1 : 0;
 
1992
        if (extended_insert && !opt_xml)
 
1993
        {
 
1994
          if (i == 0)
 
1995
          {
 
1996
            extended_row.clear();
 
1997
            extended_row.append("(");
 
1998
          }
 
1999
          else
 
2000
            extended_row.append(",");
 
2001
 
 
2002
          if (row[i])
 
2003
          {
 
2004
            if (length)
 
2005
            {
 
2006
              if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
 
2007
              {
 
2008
                /*
 
2009
                  "length * 2 + 2" is OK for both HEX and non-HEX modes:
 
2010
                  - In HEX mode we need exactly 2 bytes per character
 
2011
                  plus 2 bytes for '0x' prefix.
 
2012
                  - In non-HEX mode we need up to 2 bytes per character,
 
2013
                  plus 2 bytes for leading and trailing '\'' characters.
 
2014
                  Also we need to reserve 1 byte for terminating '\0'.
 
2015
                */
 
2016
                char * tmp_str= (char *)malloc(length * 2 + 2 + 1);
 
2017
                memset(tmp_str, '\0', length * 2 + 2 + 1);
 
2018
                if (opt_hex_blob && is_blob)
 
2019
                {
 
2020
                  extended_row.append("0x");
 
2021
                  drizzle_hex_string(tmp_str, row[i], length);
 
2022
                  extended_row.append(tmp_str);
 
2023
                }
 
2024
                else
 
2025
                {
 
2026
                  extended_row.append("'");
 
2027
                  drizzle_escape_string(tmp_str, row[i],length);
 
2028
                  extended_row.append(tmp_str);
 
2029
                  extended_row.append("'");
 
2030
                }
 
2031
                free(tmp_str);
 
2032
              }
 
2033
              else
 
2034
              {
 
2035
                /* change any strings ("inf", "-inf", "nan") into NULL */
 
2036
                char *ptr= row[i];
 
2037
                if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
 
2038
                    my_isalpha(charset_info, ptr[1])))
 
2039
                  extended_row.append( "NULL");
 
2040
                else
 
2041
                {
 
2042
                  extended_row.append( ptr);
 
2043
                }
 
2044
              }
 
2045
            }
 
2046
            else
 
2047
              extended_row.append("''");
 
2048
          }
 
2049
          else
 
2050
            extended_row.append("NULL");
 
2051
        }
 
2052
        else
 
2053
        {
 
2054
          if (i && !opt_xml)
 
2055
          {
 
2056
            fputc(',', md_result_file);
 
2057
            check_io(md_result_file);
 
2058
          }
 
2059
          if (row[i])
 
2060
          {
 
2061
            if (!(drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NUM))
 
2062
            {
 
2063
              if (opt_xml)
 
2064
              {
 
2065
                if (opt_hex_blob && is_blob && length)
 
2066
                {
 
2067
                  /* Define xsi:type="xs:hexBinary" for hex encoded data */
 
2068
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2069
                                drizzle_column_name(column), "xsi:type=", "xs:hexBinary", NULL);
 
2070
                  print_blob_as_hex(md_result_file, row[i], length);
 
2071
                }
 
2072
                else
 
2073
                {
 
2074
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2075
                                drizzle_column_name(column), NULL);
 
2076
                  print_quoted_xml(md_result_file, row[i], length);
 
2077
                }
 
2078
                fputs("</field>\n", md_result_file);
 
2079
              }
 
2080
              else if (opt_hex_blob && is_blob && length)
 
2081
              {
 
2082
                fputs("0x", md_result_file);
 
2083
                print_blob_as_hex(md_result_file, row[i], length);
 
2084
              }
 
2085
              else
 
2086
                unescape(md_result_file, row[i], length);
 
2087
            }
 
2088
            else
 
2089
            {
 
2090
              /* change any strings ("inf", "-inf", "nan") into NULL */
 
2091
              char *ptr= row[i];
 
2092
              if (opt_xml)
 
2093
              {
 
2094
                print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
 
2095
                        drizzle_column_name(column), NULL);
 
2096
                fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
 
2097
                      md_result_file);
 
2098
                fputs("</field>\n", md_result_file);
 
2099
              }
 
2100
              else if (my_isalpha(charset_info, *ptr) ||
 
2101
                       (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
 
2102
                fputs("NULL", md_result_file);
 
2103
              else
 
2104
                fputs(ptr, md_result_file);
 
2105
            }
 
2106
          }
 
2107
          else
 
2108
          {
 
2109
            /* The field value is NULL */
 
2110
            if (!opt_xml)
 
2111
              fputs("NULL", md_result_file);
 
2112
            else
 
2113
              print_xml_null_tag(md_result_file, "\t\t", "field name=",
 
2114
                                 drizzle_column_name(column), "\n");
 
2115
          }
 
2116
          check_io(md_result_file);
 
2117
        }
 
2118
      }
 
2119
 
 
2120
      if (opt_xml)
 
2121
      {
 
2122
        fputs("\t</row>\n", md_result_file);
 
2123
        check_io(md_result_file);
 
2124
      }
 
2125
 
 
2126
      if (extended_insert)
 
2127
      {
 
2128
        uint32_t row_length;
 
2129
        extended_row.append(")");
 
2130
        row_length= 2 + extended_row.length();
 
2131
        if (total_length + row_length < DRIZZLE_MAX_LINE_LENGTH)
 
2132
        {
 
2133
          total_length+= row_length;
 
2134
          fputc(',',md_result_file);            /* Always row break */
 
2135
          fputs(extended_row.c_str(),md_result_file);
 
2136
        }
 
2137
        else
 
2138
        {
 
2139
          if (row_break)
 
2140
            fputs(";\n", md_result_file);
 
2141
          row_break=1;                          /* This is first row */
 
2142
 
 
2143
          fputs(insert_pat.c_str(),md_result_file);
 
2144
          fputs(extended_row.c_str(),md_result_file);
 
2145
          total_length= row_length+init_length;
 
2146
        }
 
2147
        check_io(md_result_file);
 
2148
      }
 
2149
      else if (!opt_xml)
 
2150
      {
 
2151
        fputs(");\n", md_result_file);
 
2152
        check_io(md_result_file);
 
2153
      }
 
2154
    }
 
2155
 
 
2156
    /* XML - close table tag and supress regular output */
 
2157
    if (opt_xml)
 
2158
        fputs("\t</table_data>\n", md_result_file);
 
2159
    else if (extended_insert && row_break)
 
2160
      fputs(";\n", md_result_file);             /* If not empty table */
 
2161
    fflush(md_result_file);
 
2162
    check_io(md_result_file);
 
2163
 
 
2164
    /* Moved enable keys to before unlock per bug 15977 */
 
2165
    if (opt_disable_keys)
 
2166
    {
 
2167
      fprintf(md_result_file,"ALTER TABLE %s ENABLE KEYS;\n",
 
2168
              opt_quoted_table);
 
2169
      check_io(md_result_file);
 
2170
    }
 
2171
    if (opt_autocommit)
 
2172
    {
 
2173
      fprintf(md_result_file, "commit;\n");
 
2174
      check_io(md_result_file);
 
2175
    }
 
2176
    drizzle_result_free(&result);
 
2177
  }
 
2178
  return;
 
2179
 
 
2180
err:
 
2181
  maybe_exit(error);
 
2182
  return;
 
2183
} /* dump_table */
 
2184
 
 
2185
 
 
2186
static char *getTableName(int reset)
 
2187
{
 
2188
  static drizzle_result_st result;
 
2189
  static bool have_result= false;
 
2190
  drizzle_row_t row;
 
2191
 
 
2192
  if (!have_result)
 
2193
  {
 
2194
    if (drizzleclient_query_with_error_report(&dcon, &result, "SHOW TABLES", false))
 
2195
      return NULL;
 
2196
    have_result= true;
 
2197
  }
 
2198
 
 
2199
  if ((row= drizzle_row_next(&result)))
 
2200
    return row[0];
 
2201
 
 
2202
  if (reset)
 
2203
    drizzle_row_seek(&result, 0);
 
2204
  else
 
2205
  {
 
2206
    drizzle_result_free(&result);
 
2207
    have_result= false;
 
2208
  }
 
2209
  return NULL;
 
2210
} /* getTableName */
 
2211
 
 
2212
 
365
2213
static int dump_all_databases()
366
2214
{
367
2215
  drizzle_row_t row;
368
 
  drizzle_result_st *tableres;
 
2216
  drizzle_result_st tableres;
369
2217
  int result=0;
370
 
  std::string query;
371
 
  DrizzleDumpDatabase *database;
372
 
 
373
 
  if (verbose)
374
 
    std::cerr << _("-- Retrieving database structures...") << std::endl;
375
 
 
376
 
  /* Blocking the MySQL privilege tables too because we can't import them due to bug#646187 */
377
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
378
 
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')";
379
 
  else
380
 
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM DATA_DICTIONARY.SCHEMAS WHERE SCHEMA_NAME NOT IN ('information_schema','data_dictionary')";
381
 
 
382
 
  tableres= db_connection->query(query);
383
 
  while ((row= drizzle_row_next(tableres)))
 
2218
 
 
2219
  if (drizzleclient_query_with_error_report(&dcon, &tableres, "SHOW DATABASES", false))
 
2220
    return 1;
 
2221
  while ((row= drizzle_row_next(&tableres)))
384
2222
  {
385
 
    std::string database_name(row[0]);
386
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
387
 
      database= new DrizzleDumpDatabaseMySQL(database_name, db_connection);
388
 
    else
389
 
      database= new DrizzleDumpDatabaseDrizzle(database_name, db_connection);
390
 
 
391
 
    database->setCollate(row[1]);
392
 
    database_store.push_back(database);
 
2223
    if (dump_all_tables_in_db(row[0]))
 
2224
      result=1;
393
2225
  }
394
 
  db_connection->freeResult(tableres);
 
2226
  drizzle_result_free(&tableres);
395
2227
  return result;
396
2228
}
397
2229
/* dump_all_databases */
398
2230
 
399
2231
 
400
 
static int dump_databases(const vector<string> &db_names)
 
2232
static int dump_databases(char **db_names)
401
2233
{
402
2234
  int result=0;
403
 
  string temp;
404
 
  DrizzleDumpDatabase *database;
405
 
 
406
 
  for (vector<string>::const_iterator it= db_names.begin(); it != db_names.end(); ++it)
 
2235
  char **db;
 
2236
 
 
2237
 
 
2238
  for (db= db_names ; *db ; db++)
407
2239
  {
408
 
    temp= *it;
409
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
410
 
      database= new DrizzleDumpDatabaseMySQL(temp, db_connection);
411
 
    else
412
 
      database= new DrizzleDumpDatabaseDrizzle(temp, db_connection);
413
 
    database_store.push_back(database);
 
2240
    if (dump_all_tables_in_db(*db))
 
2241
      result=1;
414
2242
  }
415
2243
  return(result);
416
2244
} /* dump_databases */
417
2245
 
418
 
static int dump_selected_tables(const string &db, const vector<string> &table_names)
419
 
{
420
 
  DrizzleDumpDatabase *database;
421
 
 
422
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
423
 
    database= new DrizzleDumpDatabaseMySQL(db, db_connection);
424
 
  else
425
 
    database= new DrizzleDumpDatabaseDrizzle(db, db_connection);
426
 
 
427
 
  if (not database->populateTables(table_names))
428
 
  {
429
 
    delete database;
430
 
    if (not ignore_errors)
431
 
      maybe_exit(EX_DRIZZLEERR);
432
 
  }
433
 
 
434
 
  database_store.push_back(database); 
435
 
 
 
2246
 
 
2247
/*
 
2248
Table Specific database initalization.
 
2249
 
 
2250
SYNOPSIS
 
2251
  init_dumping_tables
 
2252
  qdatabase      quoted name of the database
 
2253
 
 
2254
RETURN VALUES
 
2255
  0        Success.
 
2256
  1        Failure.
 
2257
*/
 
2258
 
 
2259
int init_dumping_tables(char *qdatabase)
 
2260
{
 
2261
  if (!opt_create_db)
 
2262
  {
 
2263
    char qbuf[256];
 
2264
    drizzle_row_t row;
 
2265
    drizzle_result_st result;
 
2266
    drizzle_return_t ret;
 
2267
 
 
2268
    snprintf(qbuf, sizeof(qbuf),
 
2269
             "SHOW CREATE DATABASE IF NOT EXISTS %s",
 
2270
             qdatabase);
 
2271
 
 
2272
    if (drizzle_query_str(&dcon, &result, qbuf, &ret) == NULL ||
 
2273
        ret != DRIZZLE_RETURN_OK)
 
2274
    {
 
2275
      if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
2276
        drizzle_result_free(&result);
 
2277
 
 
2278
      /* Old server version, dump generic CREATE DATABASE */
 
2279
      if (opt_drop_database)
 
2280
        fprintf(md_result_file,
 
2281
                "\nDROP DATABASE IF EXISTS %s;\n",
 
2282
                qdatabase);
 
2283
      fprintf(md_result_file,
 
2284
              "\nCREATE DATABASE IF NOT EXISTS %s;\n",
 
2285
              qdatabase);
 
2286
    }
 
2287
    else
 
2288
    {
 
2289
      if (drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
 
2290
      {
 
2291
        if (opt_drop_database)
 
2292
          fprintf(md_result_file,
 
2293
                  "\nDROP DATABASE IF EXISTS %s;\n",
 
2294
                  qdatabase);
 
2295
        row = drizzle_row_next(&result);
 
2296
        if (row != NULL && row[1])
 
2297
        {
 
2298
          fprintf(md_result_file,"\n%s;\n",row[1]);
 
2299
        }
 
2300
      }
 
2301
      drizzle_result_free(&result);
 
2302
    }
 
2303
  }
 
2304
  return(0);
 
2305
} /* init_dumping_tables */
 
2306
 
 
2307
 
 
2308
static int init_dumping(char *database, int init_func(char*))
 
2309
{
 
2310
  drizzle_result_st result;
 
2311
  drizzle_return_t ret;
 
2312
 
 
2313
  if (!my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
 
2314
    return 1;
 
2315
 
 
2316
  if (drizzle_select_db(&dcon, &result, database, &ret) == NULL ||
 
2317
        ret != DRIZZLE_RETURN_OK)
 
2318
  {
 
2319
    DB_error(&result, ret, _("when executing 'SELECT INTO OUTFILE'"));
 
2320
    return 1;                   /* If --force */
 
2321
  }
 
2322
  drizzle_result_free(&result);
 
2323
 
 
2324
  if (!path && !opt_xml)
 
2325
  {
 
2326
    if (opt_databases || opt_alldbs)
 
2327
    {
 
2328
      /*
 
2329
        length of table name * 2 (if name contains quotes), 2 quotes and 0
 
2330
      */
 
2331
      char quoted_database_buf[DRIZZLE_MAX_DB_SIZE*2+3];
 
2332
      char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
 
2333
      if (opt_comments)
 
2334
      {
 
2335
        fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
 
2336
        check_io(md_result_file);
 
2337
      }
 
2338
 
 
2339
      /* Call the view or table specific function */
 
2340
      init_func(qdatabase);
 
2341
 
 
2342
      fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
 
2343
      check_io(md_result_file);
 
2344
    }
 
2345
  }
 
2346
  if (extended_insert)
 
2347
    extended_row.clear();
 
2348
  return 0;
 
2349
} /* init_dumping */
 
2350
 
 
2351
 
 
2352
/* Return 1 if we should copy the table */
 
2353
 
 
2354
static bool include_table(const char *hash_key, size_t key_size)
 
2355
{
 
2356
  string match(hash_key, key_size);
 
2357
  drizzled::hash_set<string>::iterator iter= ignore_table.find(match);
 
2358
  return (iter == ignore_table.end());
 
2359
}
 
2360
 
 
2361
 
 
2362
static int dump_all_tables_in_db(char *database)
 
2363
{
 
2364
  char *table;
 
2365
  char hash_key[DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2];  /* "db.tablename" */
 
2366
  char *afterdot;
 
2367
  drizzle_result_st result;
 
2368
  drizzle_return_t ret;
 
2369
 
 
2370
  memset(hash_key, 0, DRIZZLE_MAX_DB_SIZE+DRIZZLE_MAX_TABLE_SIZE+2);
 
2371
  afterdot= strcpy(hash_key, database) + strlen(database);
 
2372
  *afterdot++= '.';
 
2373
 
 
2374
  if (init_dumping(database, init_dumping_tables))
 
2375
    return(1);
 
2376
  if (opt_xml)
 
2377
    print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NULL);
 
2378
  if (flush_logs)
 
2379
  {
 
2380
    if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
 
2381
        ret != DRIZZLE_RETURN_OK)
 
2382
    {
 
2383
      DB_error(&result, ret, _("when doing refresh"));
 
2384
      /* We shall continue here, if --force was given */
 
2385
    }
 
2386
    else
 
2387
      drizzle_result_free(&result);
 
2388
  }
 
2389
  while ((table= getTableName(0)))
 
2390
  {
 
2391
    char *end= strcpy(afterdot, table) + strlen(table);
 
2392
    if (include_table(hash_key, end - hash_key))
 
2393
    {
 
2394
      dump_table(table,database);
 
2395
      free(order_by);
 
2396
      order_by= 0;
 
2397
    }
 
2398
  }
 
2399
  if (opt_xml)
 
2400
  {
 
2401
    fputs("</database>\n", md_result_file);
 
2402
    check_io(md_result_file);
 
2403
  }
 
2404
 
 
2405
  return 0;
 
2406
} /* dump_all_tables_in_db */
 
2407
 
 
2408
 
 
2409
/*
 
2410
  get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
 
2411
  table name from the server for the table name given on the command line.
 
2412
  we do this because the table name given on the command line may be a
 
2413
  different case (e.g.  T1 vs t1)
 
2414
 
 
2415
  RETURN
 
2416
    pointer to the table name
 
2417
    0 if error
 
2418
*/
 
2419
 
 
2420
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
 
2421
{
 
2422
  char *name= 0;
 
2423
  drizzle_result_st result;
 
2424
  drizzle_row_t  row;
 
2425
  char query[50 + 2*DRIZZLE_MAX_TABLE_SIZE];
 
2426
  char show_name_buff[FN_REFLEN];
 
2427
  uint64_t num_rows;
 
2428
 
 
2429
 
 
2430
  /* Check memory for quote_for_like() */
 
2431
  assert(2*sizeof(old_table_name) < sizeof(show_name_buff));
 
2432
  snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
 
2433
           quote_for_like(old_table_name, show_name_buff));
 
2434
 
 
2435
  if (drizzleclient_query_with_error_report(&dcon, &result, query, false))
 
2436
    return NULL;
 
2437
 
 
2438
  num_rows= drizzle_result_row_count(&result);
 
2439
  if (num_rows > 0)
 
2440
  {
 
2441
    size_t *lengths;
 
2442
    /*
 
2443
      Return first row
 
2444
      TODO: Return all matching rows
 
2445
    */
 
2446
    row= drizzle_row_next(&result);
 
2447
    lengths= drizzle_row_field_sizes(&result);
 
2448
    name= strmake_root(root, row[0], lengths[0]);
 
2449
  }
 
2450
  drizzle_result_free(&result);
 
2451
 
 
2452
  return(name);
 
2453
}
 
2454
 
 
2455
 
 
2456
static int dump_selected_tables(char *db, char **table_names, int tables)
 
2457
{
 
2458
  MEM_ROOT root;
 
2459
  char **dump_tables, **pos, **end;
 
2460
  drizzle_result_st result;
 
2461
  drizzle_return_t ret;
 
2462
 
 
2463
 
 
2464
  if (init_dumping(db, init_dumping_tables))
 
2465
    return(1);
 
2466
 
 
2467
  init_alloc_root(&root, 8192, 0);
 
2468
  if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
 
2469
     die(EX_EOM, _("alloc_root failure."));
 
2470
 
 
2471
  for (; tables > 0 ; tables-- , table_names++)
 
2472
  {
 
2473
    /* the table name passed on commandline may be wrong case */
 
2474
    if ((*pos= get_actual_table_name(*table_names, &root)))
 
2475
    {
 
2476
      pos++;
 
2477
    }
 
2478
    else
 
2479
    {
 
2480
      if (!ignore_errors)
 
2481
      {
 
2482
        free_root(&root, MYF(0));
 
2483
      }
 
2484
      maybe_die(EX_ILLEGAL_TABLE, _("Couldn't find table: \"%s\""), *table_names);
 
2485
      /* We shall countinue here, if --force was given */
 
2486
    }
 
2487
  }
 
2488
  end= pos;
 
2489
 
 
2490
  if (flush_logs)
 
2491
  {
 
2492
    if (drizzle_query_str(&dcon, &result, "FLUSH LOGS", &ret) == NULL ||
 
2493
        ret != DRIZZLE_RETURN_OK)
 
2494
    {
 
2495
      if (!ignore_errors)
 
2496
        free_root(&root, MYF(0));
 
2497
      DB_error(&result, ret, _("when doing refresh"));
 
2498
      /* We shall countinue here, if --force was given */
 
2499
    }
 
2500
    else
 
2501
      drizzle_result_free(&result);
 
2502
  }
 
2503
  if (opt_xml)
 
2504
    print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NULL);
 
2505
 
 
2506
  /* Dump each selected table */
 
2507
  for (pos= dump_tables; pos < end; pos++)
 
2508
    dump_table(*pos, db);
 
2509
 
 
2510
  free_root(&root, MYF(0));
 
2511
  free(order_by);
 
2512
  order_by= 0;
 
2513
  if (opt_xml)
 
2514
  {
 
2515
    fputs("</database>\n", md_result_file);
 
2516
    check_io(md_result_file);
 
2517
  }
436
2518
  return 0;
437
2519
} /* dump_selected_tables */
438
2520
 
439
 
static int do_flush_tables_read_lock()
 
2521
static int do_flush_tables_read_lock(drizzle_con_st *drizzle_con)
440
2522
{
441
2523
  /*
442
2524
    We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
443
2525
    will wait but will not stall the whole mysqld, and when the long update is
444
2526
    done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
445
 
    FLUSH TABLES is to lower the probability of a stage where both drizzled
 
2527
    FLUSH TABLES is to lower the probability of a stage where both mysqldump
446
2528
    and most client connections are stalled. Of course, if a second long
447
2529
    update starts between the two FLUSHes, we have that bad stall.
448
2530
  */
449
 
 
450
 
   db_connection->queryNoResult("FLUSH TABLES");
451
 
   db_connection->queryNoResult("FLUSH TABLES WITH READ LOCK");
452
 
 
453
 
  return 0;
454
 
}
455
 
 
456
 
static int do_unlock_tables()
457
 
{
458
 
  db_connection->queryNoResult("UNLOCK TABLES");
459
 
  return 0;
460
 
}
461
 
 
462
 
static int start_transaction()
463
 
{
464
 
  db_connection->queryNoResult("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ");
465
 
  db_connection->queryNoResult("START TRANSACTION WITH CONSISTENT SNAPSHOT");
466
 
  return 0;
467
 
}
 
2531
  return
 
2532
    ( drizzleclient_query_with_error_report(drizzle_con, 0, "FLUSH TABLES", false) ||
 
2533
      drizzleclient_query_with_error_report(drizzle_con, 0,
 
2534
                                    "FLUSH TABLES WITH READ LOCK", false) );
 
2535
}
 
2536
 
 
2537
static int do_unlock_tables(drizzle_con_st *drizzle_con)
 
2538
{
 
2539
  return drizzleclient_query_with_error_report(drizzle_con, 0, "UNLOCK TABLES", false);
 
2540
}
 
2541
 
 
2542
static int start_transaction(drizzle_con_st *drizzle_con)
 
2543
{
 
2544
  return (drizzleclient_query_with_error_report(drizzle_con, 0,
 
2545
                                        "SET SESSION TRANSACTION ISOLATION "
 
2546
                                        "LEVEL REPEATABLE READ", false) ||
 
2547
          drizzleclient_query_with_error_report(drizzle_con, 0,
 
2548
                                        "START TRANSACTION "
 
2549
                                        "WITH CONSISTENT SNAPSHOT", false));
 
2550
}
 
2551
 
 
2552
 
 
2553
static uint32_t find_set(TYPELIB *lib, const char *x, uint32_t length,
 
2554
                      char **err_pos, uint32_t *err_len)
 
2555
{
 
2556
  const char *end= x + length;
 
2557
  uint32_t found= 0;
 
2558
  uint32_t find;
 
2559
  char buff[255];
 
2560
 
 
2561
  *err_pos= 0;                  /* No error yet */
 
2562
  while (end > x && my_isspace(charset_info, end[-1]))
 
2563
    end--;
 
2564
 
 
2565
  *err_len= 0;
 
2566
  if (x != end)
 
2567
  {
 
2568
    const char *start= x;
 
2569
    for (;;)
 
2570
    {
 
2571
      const char *pos= start;
 
2572
      uint32_t var_len;
 
2573
 
 
2574
      for (; pos != end && *pos != ','; pos++) ;
 
2575
      var_len= (uint32_t) (pos - start);
 
2576
      strncpy(buff, start, min((uint32_t)sizeof(buff), var_len+1));
 
2577
      find= find_type(buff, lib, var_len);
 
2578
      if (!find)
 
2579
      {
 
2580
        *err_pos= (char*) start;
 
2581
        *err_len= var_len;
 
2582
      }
 
2583
      else
 
2584
        found|= (uint32_t)((int64_t) 1 << (find - 1));
 
2585
      if (pos == end)
 
2586
        break;
 
2587
      start= pos + 1;
 
2588
    }
 
2589
  }
 
2590
  return found;
 
2591
}
 
2592
 
 
2593
 
 
2594
/* Print a value with a prefix on file */
 
2595
static void print_value(FILE *file, drizzle_result_st  *result, drizzle_row_t row,
 
2596
                        const char *prefix, const char *name,
 
2597
                        int string_value)
 
2598
{
 
2599
  drizzle_column_st *column;
 
2600
  drizzle_column_seek(result, 0);
 
2601
 
 
2602
  for ( ; (column= drizzle_column_next(result)) ; row++)
 
2603
  {
 
2604
    if (!strcmp(drizzle_column_name(column),name))
 
2605
    {
 
2606
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
2607
      {
 
2608
        fputc(' ',file);
 
2609
        fputs(prefix, file);
 
2610
        if (string_value)
 
2611
          unescape(file,row[0],(uint32_t) strlen(row[0]));
 
2612
        else
 
2613
          fputs(row[0], file);
 
2614
        check_io(file);
 
2615
        return;
 
2616
      }
 
2617
    }
 
2618
  }
 
2619
  return;                                       /* This shouldn't happen */
 
2620
} /* print_value */
 
2621
 
 
2622
/**
 
2623
 * Fetches a row from a result based on a field name
 
2624
 * Returns const char* of the data in that row or NULL if not found
 
2625
 */
 
2626
 
 
2627
static const char* fetch_named_row(drizzle_result_st *result, drizzle_row_t row, const char *name)
 
2628
{
 
2629
  drizzle_column_st *column;
 
2630
  drizzle_column_seek(result, 0);
 
2631
 
 
2632
  for ( ; (column= drizzle_column_next(result)) ; row++)
 
2633
  {
 
2634
    if (!strcmp(drizzle_column_name(column),name))
 
2635
    {
 
2636
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
 
2637
      {
 
2638
        drizzle_column_seek(result, 0);
 
2639
        return row[0];
 
2640
      }
 
2641
    }
 
2642
  }
 
2643
  drizzle_column_seek(result, 0);
 
2644
  return NULL;
 
2645
}
 
2646
 
 
2647
 
 
2648
/*
 
2649
  SYNOPSIS
 
2650
 
 
2651
  Check if we the table is one of the table types that should be ignored:
 
2652
  MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
 
2653
  If the table should be altogether ignored, it returns a true, false if it
 
2654
  should not be ignored. If the user has selected to use INSERT DELAYED, it
 
2655
  sets the value of the bool pointer supports_delayed_inserts to 0 if not
 
2656
  supported, 1 if it is supported.
 
2657
 
 
2658
  ARGS
 
2659
 
 
2660
    check_if_ignore_table()
 
2661
    table_name                  Table name to check
 
2662
    table_type                  Type of table
 
2663
 
 
2664
  GLOBAL VARIABLES
 
2665
    drizzle                       Drizzle connection
 
2666
    verbose                     Write warning messages
 
2667
 
 
2668
  RETURN
 
2669
    char (bit value)            See IGNORE_ values at top
 
2670
*/
 
2671
 
 
2672
char check_if_ignore_table(const char *table_name, char *table_type)
 
2673
{
 
2674
  char result= IGNORE_NONE;
 
2675
  char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
 
2676
  const char *number_of_rows= NULL;
 
2677
  drizzle_result_st res;
 
2678
  drizzle_row_t row;
 
2679
 
 
2680
  /* Check memory for quote_for_like() */
 
2681
  assert(2*sizeof(table_name) < sizeof(show_name_buff));
 
2682
  snprintf(buff, sizeof(buff), "show table status like %s",
 
2683
           quote_for_like(table_name, show_name_buff));
 
2684
  if (drizzleclient_query_with_error_report(&dcon, &res, buff, false))
 
2685
  {
 
2686
    return result;
 
2687
  }
 
2688
  if (!(row= drizzle_row_next(&res)))
 
2689
  {
 
2690
    fprintf(stderr,
 
2691
            _("Error: Couldn't read status information for table %s\n"),
 
2692
            table_name);
 
2693
    drizzle_result_free(&res);
 
2694
    return(result);                         /* assume table is ok */
 
2695
  }
 
2696
  else
 
2697
  {
 
2698
    if ((number_of_rows= fetch_named_row(&res, row, "Rows")) != NULL)
 
2699
    {
 
2700
      total_rows= strtoul(number_of_rows, NULL, 10);
 
2701
    }
 
2702
  }
 
2703
  /*
 
2704
    If the table type matches any of these, we do support delayed inserts.
 
2705
    Note: we do not want to skip dumping this table if if is not one of
 
2706
    these types, but we do want to use delayed inserts in the dump if
 
2707
    the table type is _NOT_ one of these types
 
2708
    */
 
2709
  {
 
2710
    strncpy(table_type, row[1], DRIZZLE_MAX_TABLE_SIZE-1);
 
2711
    if (opt_delayed)
 
2712
    {
 
2713
      if (strcmp(table_type,"MyISAM") &&
 
2714
          strcmp(table_type,"ARCHIVE") &&
 
2715
          strcmp(table_type,"HEAP") &&
 
2716
          strcmp(table_type,"MEMORY"))
 
2717
        result= IGNORE_INSERT_DELAYED;
 
2718
    }
 
2719
  }
 
2720
  drizzle_result_free(&res);
 
2721
  return(result);
 
2722
}
 
2723
 
 
2724
 
 
2725
/*
 
2726
  Get string of comma-separated primary key field names
 
2727
 
 
2728
  SYNOPSIS
 
2729
    char *primary_key_fields(const char *table_name)
 
2730
    RETURNS     pointer to allocated buffer (must be freed by caller)
 
2731
    table_name  quoted table name
 
2732
 
 
2733
  DESCRIPTION
 
2734
    Use SHOW KEYS FROM table_name, allocate a buffer to hold the
 
2735
    field names, and then build that string and return the pointer
 
2736
    to that buffer.
 
2737
 
 
2738
    Returns NULL if there is no PRIMARY or UNIQUE key on the table,
 
2739
    or if there is some failure.  It is better to continue to dump
 
2740
    the table unsorted, rather than exit without dumping the data.
 
2741
*/
 
2742
 
 
2743
static char *primary_key_fields(const char *table_name)
 
2744
{
 
2745
  drizzle_result_st res;
 
2746
  drizzle_return_t ret;
 
2747
  drizzle_row_t  row;
 
2748
  /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
 
2749
  char show_keys_buff[15 + DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
 
2750
  uint32_t result_length= 0;
 
2751
  char *result= 0;
 
2752
  char buff[DRIZZLE_MAX_TABLE_SIZE * 2 + 3];
 
2753
  char *quoted_field;
 
2754
 
 
2755
  snprintf(show_keys_buff, sizeof(show_keys_buff),
 
2756
           "SHOW KEYS FROM %s", table_name);
 
2757
  if (drizzle_query_str(&dcon, &res, show_keys_buff, &ret) == NULL ||
 
2758
      ret != DRIZZLE_RETURN_OK)
 
2759
  {
 
2760
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
2761
    {
 
2762
      fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
2763
              " records are NOT sorted (%s)\n"),
 
2764
              table_name, drizzle_result_error(&res));
 
2765
      drizzle_result_free(&res);
 
2766
    }
 
2767
    else
 
2768
    {
 
2769
      fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
2770
              " records are NOT sorted (%s)\n"),
 
2771
              table_name, drizzle_con_error(&dcon));
 
2772
    }
 
2773
 
 
2774
    return result;
 
2775
  }
 
2776
 
 
2777
  if (drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
 
2778
  {
 
2779
    fprintf(stderr, _("Warning: Couldn't read keys from table %s;"
 
2780
            " records are NOT sorted (%s)\n"),
 
2781
            table_name, drizzle_con_error(&dcon));
 
2782
    return result;
 
2783
  }
 
2784
 
 
2785
  /*
 
2786
   * Figure out the length of the ORDER BY clause result.
 
2787
   * Note that SHOW KEYS is ordered:  a PRIMARY key is always the first
 
2788
   * row, and UNIQUE keys come before others.  So we only need to check
 
2789
   * the first key, not all keys.
 
2790
   */
 
2791
  if ((row= drizzle_row_next(&res)) && atoi(row[1]) == 0)
 
2792
  {
 
2793
    /* Key is unique */
 
2794
    do
 
2795
    {
 
2796
      quoted_field= quote_name(row[4], buff, 0);
 
2797
      result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
 
2798
    } while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1);
 
2799
  }
 
2800
 
 
2801
  /* Build the ORDER BY clause result */
 
2802
  if (result_length)
 
2803
  {
 
2804
    char *end;
 
2805
    /* result (terminating \0 is already in result_length) */
 
2806
    result= (char *)malloc(result_length + 10);
 
2807
    if (!result)
 
2808
    {
 
2809
      fprintf(stderr, _("Error: Not enough memory to store ORDER BY clause\n"));
 
2810
      drizzle_result_free(&res);
 
2811
      return result;
 
2812
    }
 
2813
    drizzle_row_seek(&res, 0);
 
2814
    row= drizzle_row_next(&res);
 
2815
    quoted_field= quote_name(row[4], buff, 0);
 
2816
    end= strcpy(result, quoted_field) + strlen(quoted_field);
 
2817
    while ((row= drizzle_row_next(&res)) && atoi(row[3]) > 1)
 
2818
    {
 
2819
      quoted_field= quote_name(row[4], buff, 0);
 
2820
      end+= sprintf(end,",%s",quoted_field);
 
2821
    }
 
2822
  }
 
2823
 
 
2824
  drizzle_result_free(&res);
 
2825
  return result;
 
2826
}
 
2827
 
468
2828
 
469
2829
int main(int argc, char **argv)
470
2830
{
471
 
try
472
 
{
473
2831
  int exit_code;
474
 
 
475
 
  po::options_description commandline_options(N_("Options used only in command line"));
476
 
  commandline_options.add_options()
477
 
  ("all-databases,A", po::value<bool>(&opt_alldbs)->default_value(false)->zero_tokens(),
478
 
  N_("Dump all the databases. This will be same as --databases with all databases selected."))
479
 
  ("all-tablespaces,Y", po::value<bool>(&opt_alltspcs)->default_value(false)->zero_tokens(),
480
 
  N_("Dump all the tablespaces."))
481
 
  ("complete-insert,c", po::value<bool>(&opt_complete_insert)->default_value(false)->zero_tokens(),
482
 
  N_("Use complete insert statements."))
483
 
  ("flush-logs,F", po::value<bool>(&flush_logs)->default_value(false)->zero_tokens(),
484
 
  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"))
485
 
  ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
486
 
  N_("Continue even if we get an sql-error."))
487
 
  ("help,?", N_("Display this help message and exit."))
488
 
  ("lock-all-tables,x", po::value<bool>(&opt_lock_all_tables)->default_value(false)->zero_tokens(),
489
 
  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 off."))
490
 
  ("single-transaction", po::value<bool>(&opt_single_transaction)->default_value(false)->zero_tokens(),
491
 
  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."))
492
 
  ("skip-opt", 
493
 
  N_("Disable --opt. Disables --add-drop-table, --add-locks, --create-options, ---extended-insert and --disable-keys."))    
494
 
  ("tables", N_("Overrides option --databases (-B)."))
495
 
  ("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(10000),
496
 
  N_("Number of rows before each output progress report (requires --verbose)."))
497
 
  ("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
498
 
  N_("Print info about the various stages."))
499
 
  ("version,V", N_("Output version information and exit."))
500
 
  ("skip-comments", N_("Turn off Comments"))
501
 
  ("skip-create", N_("Turn off create-options"))
502
 
  ("skip-extended-insert", N_("Turn off extended-insert"))
503
 
  ("skip-dump-date",N_( "Turn off dump date at the end of the output"))
504
 
  ("no-defaults", N_("Do not read from the configuration files"))
505
 
  ;
506
 
 
507
 
  po::options_description dump_options(N_("Options specific to the drizzle client"));
508
 
  dump_options.add_options()
509
 
  ("add-drop-database", po::value<bool>(&opt_drop_database)->default_value(false)->zero_tokens(),
510
 
  N_("Add a 'DROP DATABASE' before each create."))
511
 
  ("skip-drop-table", N_("Do not add a 'drop table' before each create."))
512
 
  ("compact", po::value<bool>(&opt_compact)->default_value(false)->zero_tokens(),
513
 
  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"))
514
 
  ("databases,B", po::value<bool>(&opt_databases)->default_value(false)->zero_tokens(),
515
 
  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."))
516
 
  ("skip-disable-keys,K",
517
 
  N_("'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will not be put in the output."))
518
 
  ("ignore-table", po::value<string>(),
519
 
  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"))
520
 
  ("insert-ignore", po::value<bool>(&opt_ignore)->default_value(false)->zero_tokens(),
521
 
  N_("Insert rows with INSERT IGNORE."))
522
 
  ("no-autocommit", po::value<bool>(&opt_autocommit)->default_value(false)->zero_tokens(),
523
 
  N_("Wrap a table's data in START TRANSACTION/COMMIT statements."))
524
 
  ("no-create-db,n", po::value<bool>(&opt_create_db)->default_value(false)->zero_tokens(),
525
 
  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."))
526
 
  ("no-data,d", po::value<bool>(&opt_no_data)->default_value(false)->zero_tokens(),
527
 
  N_("No row information."))
528
 
  ("replace", po::value<bool>(&opt_replace_into)->default_value(false)->zero_tokens(),
529
 
  N_("Use REPLACE INTO instead of INSERT INTO."))
530
 
  ("destination-type", po::value<string>()->default_value("stdout"),
531
 
  N_("Where to send output to (stdout|database"))
532
 
  ("destination-host", po::value<string>(&opt_destination_host)->default_value("localhost"),
533
 
  N_("Hostname for destination db server (requires --destination-type=database)"))
534
 
  ("destination-port", po::value<uint16_t>(&opt_destination_port)->default_value(4427),
535
 
  N_("Port number for destination db server (requires --destination-type=database)"))
536
 
  ("destination-user", po::value<string>(&opt_destination_user),
537
 
  N_("User name for destination db server (resquires --destination-type=database)"))
538
 
  ("destination-password", po::value<string>(&opt_destination_password),
539
 
  N_("Password for destination db server (requires --destination-type=database)"))
540
 
  ("destination-database", po::value<string>(&opt_destination_database),
541
 
  N_("The database in the destination db server (requires --destination-type=database, not for use with --all-databases)"))
542
 
  ;
543
 
 
544
 
  po::options_description client_options(N_("Options specific to the client"));
545
 
  client_options.add_options()
546
 
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
547
 
  N_("Connect to host."))
548
 
  ("password,P", po::value<string>(&password)->default_value(PASSWORD_SENTINEL),
549
 
  N_("Password to use when connecting to server. If password is not given it's solicited on the tty."))
550
 
  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
551
 
  N_("Port number to use for connection."))
552
 
  ("user,u", po::value<string>(&current_user)->default_value(""),
553
 
  N_("User for login if not current user."))
554
 
  ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
555
 
  N_("The protocol of connection (mysql or drizzle)."))
556
 
  ;
557
 
 
558
 
  po::options_description hidden_options(N_("Hidden Options"));
559
 
  hidden_options.add_options()
560
 
  ("database-used", po::value<vector<string> >(), N_("Used to select the database"))
561
 
  ("Table-used", po::value<vector<string> >(), N_("Used to select the tables"))
562
 
  ;
563
 
 
564
 
  po::options_description all_options(N_("Allowed Options + Hidden Options"));
565
 
  all_options.add(commandline_options).add(dump_options).add(client_options).add(hidden_options);
566
 
 
567
 
  po::options_description long_options(N_("Allowed Options"));
568
 
  long_options.add(commandline_options).add(dump_options).add(client_options);
569
 
 
570
 
  std::string system_config_dir_dump(SYSCONFDIR); 
571
 
  system_config_dir_dump.append("/drizzle/drizzledump.cnf");
572
 
 
573
 
  std::string system_config_dir_client(SYSCONFDIR); 
574
 
  system_config_dir_client.append("/drizzle/client.cnf");
575
 
 
576
 
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
577
 
 
578
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
579
 
  {
580
 
    char *homedir;
581
 
    homedir= getenv("HOME");
582
 
    if (homedir != NULL)
583
 
      user_config_dir.replace(0, 1, homedir);
584
 
  }
585
 
 
586
 
  po::positional_options_description p;
587
 
  p.add("database-used", 1);
588
 
  p.add("Table-used",-1);
589
 
 
590
 
  md_result_file= stdout;
591
 
 
592
 
  po::variables_map vm;
593
 
 
594
 
  // Disable allow_guessing
595
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
596
 
 
597
 
  po::store(po::command_line_parser(argc, argv).style(style).
598
 
            options(all_options).positional(p).
599
 
            extra_parser(parse_password_arg).run(), vm);
600
 
 
601
 
  if (! vm.count("no-defaults"))
602
 
  {
603
 
    std::string user_config_dir_dump(user_config_dir);
604
 
    user_config_dir_dump.append("/drizzle/drizzledump.cnf"); 
605
 
 
606
 
    std::string user_config_dir_client(user_config_dir);
607
 
    user_config_dir_client.append("/drizzle/client.cnf");
608
 
 
609
 
    ifstream user_dump_ifs(user_config_dir_dump.c_str());
610
 
    po::store(parse_config_file(user_dump_ifs, dump_options), vm);
611
 
 
612
 
    ifstream user_client_ifs(user_config_dir_client.c_str());
613
 
    po::store(parse_config_file(user_client_ifs, client_options), vm);
614
 
 
615
 
    ifstream system_dump_ifs(system_config_dir_dump.c_str());
616
 
    po::store(parse_config_file(system_dump_ifs, dump_options), vm);
617
 
 
618
 
    ifstream system_client_ifs(system_config_dir_client.c_str());
619
 
    po::store(parse_config_file(system_client_ifs, client_options), vm);
620
 
  }
621
 
 
622
 
  po::notify(vm);  
623
 
  
624
 
  if ((not vm.count("database-used") && not vm.count("Table-used") 
625
 
    && not opt_alldbs && path.empty())
626
 
    || (vm.count("help")) || vm.count("version"))
627
 
  {
628
 
    printf(_("Drizzledump %s build %s, for %s-%s (%s)\n"),
629
 
      drizzle_version(), VERSION, HOST_VENDOR, HOST_OS, HOST_CPU);
630
 
    if (vm.count("version"))
631
 
      exit(0);
632
 
    puts("");
633
 
    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"));
634
 
    puts(_("Dumps definitions and data from a Drizzle database server"));
635
 
    printf(_("Usage: %s [OPTIONS] database [tables]\n"), progname.c_str());
636
 
    printf(_("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n"),
637
 
          progname.c_str());
638
 
    printf(_("OR     %s [OPTIONS] --all-databases [OPTIONS]\n"), progname.c_str());
639
 
    cout << long_options;
640
 
    if (vm.count("help"))
641
 
      exit(0);
642
 
    else
643
 
      exit(1);
644
 
  }
645
 
 
646
 
  /* Inverted Booleans */
647
 
 
648
 
  opt_drop= (vm.count("skip-drop-table")) ? false : true;
649
 
  opt_comments= (vm.count("skip-comments")) ? false : true;
650
 
  extended_insert= (vm.count("skip-extended-insert")) ? false : true;
651
 
  opt_dump_date= (vm.count("skip-dump-date")) ? false : true;
652
 
  opt_disable_keys= (vm.count("skip-disable-keys")) ? false : true;
653
 
  opt_quoted= (vm.count("skip-quote-names")) ? false : true;
654
 
 
655
 
  if (vm.count("protocol"))
656
 
  {
657
 
    std::transform(opt_protocol.begin(), opt_protocol.end(),
658
 
      opt_protocol.begin(), ::tolower);
659
 
 
660
 
    if (not opt_protocol.compare("mysql"))
661
 
      use_drizzle_protocol=false;
662
 
    else if (not opt_protocol.compare("drizzle"))
663
 
      use_drizzle_protocol=true;
664
 
    else
665
 
    {
666
 
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
667
 
      exit(-1);
668
 
    }
669
 
  }
670
 
 
671
 
  if (vm.count("port"))
672
 
  {
673
 
    /* If the port number is > 65535 it is not a valid port
674
 
     *        This also helps with potential data loss casting unsigned long to a
675
 
     *               uint32_t. 
676
 
     */
677
 
    if (opt_drizzle_port > 65535)
678
 
    {
679
 
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
680
 
      exit(-1);
681
 
    }
682
 
  }
683
 
 
684
 
  if(vm.count("password"))
685
 
  {
686
 
    if (!opt_password.empty())
687
 
      opt_password.erase();
688
 
    if (password == PASSWORD_SENTINEL)
689
 
    {
690
 
      opt_password= "";
691
 
    }
692
 
    else
693
 
    {
694
 
      opt_password= password;
695
 
      tty_password= false;
696
 
    }
697
 
  }
698
 
  else
699
 
  {
700
 
      tty_password= true;
701
 
  }
702
 
 
703
 
  if (! path.empty())
704
 
  { 
705
 
    opt_disable_keys= 0;
706
 
  }
707
 
 
708
 
  if (vm.count("skip-opt"))
709
 
  {
710
 
    extended_insert= opt_drop= create_options= 0;
711
 
    opt_disable_keys= 0;
712
 
  }
713
 
 
714
 
  if (opt_compact)
715
 
  { 
716
 
    opt_comments= opt_drop= opt_disable_keys= 0;
717
 
  }
718
 
 
719
 
  if (vm.count("opt"))
720
 
  {
721
 
    extended_insert= opt_drop= create_options= 1;
722
 
    opt_disable_keys= 1;
723
 
  }
724
 
 
725
 
  if (vm.count("tables"))
726
 
  { 
727
 
    opt_databases= false;
728
 
  }
729
 
 
730
 
  if (vm.count("ignore-table"))
731
 
  {
732
 
    if (!strchr(vm["ignore-table"].as<string>().c_str(), '.'))
733
 
    {
734
 
      fprintf(stderr, _("Illegal use of option --ignore-table=<database>.<table>\n"));
735
 
      exit(EXIT_ARGUMENT_INVALID);
736
 
    }
737
 
    string tmpptr(vm["ignore-table"].as<string>());
738
 
    ignore_table.insert(tmpptr); 
739
 
  }
740
 
 
741
 
  if (vm.count("skip-create"))
742
 
  {
743
 
    opt_create_db= opt_no_create_info= create_options= false;
744
 
  }
745
 
 
746
 
  exit_code= get_options();
 
2832
  MY_INIT("drizzledump");
 
2833
  drizzle_result_st result;
 
2834
 
 
2835
  compatible_mode_normal_str[0]= 0;
 
2836
 
 
2837
  exit_code= get_options(&argc, &argv);
747
2838
  if (exit_code)
748
2839
  {
749
2840
    free_resources();
750
2841
    exit(exit_code);
751
2842
  }
752
 
  try
753
 
  {
754
 
    db_connection = new DrizzleDumpConnection(current_host, opt_drizzle_port,
755
 
      current_user, opt_password, use_drizzle_protocol);
756
 
  }
757
 
  catch (std::exception&)
758
 
  {
759
 
    maybe_exit(EX_DRIZZLEERR);
760
 
  }
761
 
 
762
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
763
 
    db_connection->queryNoResult("SET NAMES 'utf8'");
764
 
 
765
 
  if (vm.count("destination-type"))
766
 
  {
767
 
    string tmp_destination(vm["destination-type"].as<string>());
768
 
    if (tmp_destination.compare("database") == 0)
769
 
      opt_destination= DESTINATION_DB;
770
 
    else if (tmp_destination.compare("stdout") == 0)
771
 
      opt_destination= DESTINATION_STDOUT;
772
 
    else
773
 
      exit(EXIT_ARGUMENT_INVALID);
774
 
  }
775
 
 
776
 
 
777
 
  if (path.empty() && vm.count("database-used"))
778
 
  {
779
 
    string database_used= *vm["database-used"].as< vector<string> >().begin();
780
 
    write_header((char *)database_used.c_str());
781
 
  }
782
 
 
783
 
  if ((opt_lock_all_tables) && do_flush_tables_read_lock())
784
 
    goto err;
785
 
  if (opt_single_transaction && start_transaction())
786
 
    goto err;
 
2843
 
 
2844
  if (connect_to_db(current_host, current_user, opt_password))
 
2845
  {
 
2846
    free_resources();
 
2847
    exit(EX_DRIZZLEERR);
 
2848
  }
 
2849
  if (!path)
 
2850
    write_header(md_result_file, *argv);
 
2851
 
 
2852
  if ((opt_lock_all_tables) && do_flush_tables_read_lock(&dcon))
 
2853
    goto err;
 
2854
  if (opt_single_transaction && start_transaction(&dcon))
 
2855
      goto err;
787
2856
  if (opt_lock_all_tables)
788
 
    db_connection->queryNoResult("FLUSH LOGS");
789
 
  if (opt_single_transaction && do_unlock_tables()) /* unlock but no commit! */
 
2857
  {
 
2858
    if (drizzleclient_query_with_error_report(&dcon, &result, "FLUSH LOGS", false))
 
2859
      goto err;
 
2860
    drizzle_result_free(&result);
 
2861
    flush_logs= 0; /* not anymore; that would not be sensible */
 
2862
  }
 
2863
  if (opt_single_transaction && do_unlock_tables(&dcon)) /* unlock but no commit! */
790
2864
    goto err;
791
2865
 
792
2866
  if (opt_alldbs)
793
2867
  {
794
2868
    dump_all_databases();
795
 
    dump_all_tables();
796
2869
  }
797
 
  if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
 
2870
  else if (argc > 1 && !opt_databases)
798
2871
  {
799
 
    string database_used= *vm["database-used"].as< vector<string> >().begin();
800
2872
    /* Only one database and selected table(s) */
801
 
    dump_selected_tables(database_used, vm["Table-used"].as< vector<string> >());
802
 
  }
803
 
 
804
 
  if (vm.count("Table-used") and opt_databases)
805
 
  {
806
 
    vector<string> database_used= vm["database-used"].as< vector<string> >();
807
 
    vector<string> table_used= vm["Table-used"].as< vector<string> >();
808
 
 
809
 
    for (vector<string>::iterator it= table_used.begin();
810
 
       it != table_used.end();
811
 
       ++it)
812
 
    {
813
 
      database_used.insert(database_used.end(), *it);
814
 
    }
815
 
 
816
 
    dump_databases(database_used);
817
 
    dump_all_tables();
818
 
  }
819
 
 
820
 
  if (vm.count("database-used") && ! vm.count("Table-used"))
821
 
  {
822
 
    dump_databases(vm["database-used"].as< vector<string> >());
823
 
    dump_all_tables();
824
 
  }
825
 
 
826
 
  if (opt_destination == DESTINATION_STDOUT)
827
 
    generate_dump();
 
2873
    dump_selected_tables(*argv, (argv + 1), (argc - 1));
 
2874
  }
828
2875
  else
829
 
    generate_dump_db();
 
2876
  {
 
2877
    dump_databases(argv);
 
2878
  }
830
2879
 
831
2880
  /* ensure dumped data flushed */
832
2881
  if (md_result_file && fflush(md_result_file))
843
2892
    server.
844
2893
  */
845
2894
err:
846
 
  delete db_connection;
847
 
  delete destination_connection;
848
 
  if (path.empty())
 
2895
  dbDisconnect(current_host);
 
2896
  if (!path)
849
2897
    write_footer(md_result_file);
850
2898
  free_resources();
851
2899
 
852
2900
  if (stderror_file)
853
2901
    fclose(stderror_file);
854
 
}
855
2902
 
856
 
  catch(exception &err)
857
 
  {
858
 
    cerr << err.what() << endl;
859
 
  }
860
 
  
861
2903
  return(first_error);
862
2904
} /* main */