~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Joe Daly
  • Date: 2010-04-29 03:08:04 UTC
  • mto: This revision was merged to the branch mainline in revision 1523.
  • Revision ID: skinny.moey@gmail.com-20100429030804-ppssp19xwyrgm5of
remove com_stat_vars and rework lock in scoreboard to not lock on Sessions locating a slot they previously owned

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