~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Monty Taylor
  • Date: 2009-12-08 23:39:39 UTC
  • mto: (1240.1.8 build)
  • mto: This revision was merged to the branch mainline in revision 1241.
  • Revision ID: mordred@inaugust.com-20091208233939-w0v4o04xer9pqqhu
Make range test shut up.

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