~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

Separated BlitzCursor code out to it's own file.

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
 
72
66
 
73
67
/* Size of buffer for dump's select query */
74
68
#define QUERY_LENGTH 1536
 
69
#define DRIZZLE_MAX_LINE_LENGTH 1024*1024L-1025
75
70
 
76
71
/* ignore table flags */
77
72
#define IGNORE_NONE 0x00 /* no ignore */
78
73
#define IGNORE_DATA 0x01 /* don't dump data for this table */
79
74
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
80
75
 
81
 
bool opt_alltspcs= false;
82
 
bool opt_complete_insert= false;
83
 
bool  verbose= false;
84
 
static bool use_drizzle_protocol= false;
85
 
bool ignore_errors= false;
 
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;
86
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; 
87
94
static bool create_options= true; 
88
95
static bool opt_quoted= false;
89
 
bool opt_databases= false; 
90
 
bool opt_alldbs= false; 
 
96
static bool opt_databases= false; 
 
97
static bool opt_alldbs= false; 
 
98
static bool opt_create_db= false;
91
99
static bool opt_lock_all_tables= false;
 
100
static bool opt_set_charset= false; 
92
101
static bool opt_dump_date= true;
93
 
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;
94
106
static bool opt_single_transaction= false; 
95
 
static bool opt_comments;
96
 
static bool opt_compact;
97
 
bool opt_ignore= false;
98
 
bool opt_drop_database;
99
 
bool opt_no_create_info;
100
 
bool opt_no_data= false;
101
 
bool opt_create_db= false;
102
 
bool opt_disable_keys= true;
103
 
bool extended_insert= true;
104
 
bool opt_replace_into= false;
105
 
bool opt_drop= true; 
106
 
uint32_t show_progress_size= 0;
 
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;
107
121
static string insert_pat;
 
122
static char  *opt_password= NULL;
 
123
static char *current_user= NULL;
 
124
static char  *current_host= NULL;
 
125
static char *path= NULL;
 
126
static char *fields_terminated= NULL;
 
127
static char *lines_terminated= NULL; 
 
128
static char *enclosed= NULL;
 
129
static char *opt_enclosed= NULL;
 
130
static char *escaped= NULL;
 
131
static char *where= NULL; 
 
132
static char *order_by= NULL;
 
133
static char *opt_compatible_mode_str= NULL;
 
134
static char *err_ptr= NULL;
 
135
static char **defaults_argv= NULL;
 
136
static char compatible_mode_normal_str[255];
 
137
static uint32_t opt_compatible_mode= 0;
108
138
static uint32_t opt_drizzle_port= 0;
109
139
static int first_error= 0;
110
140
static string extended_row;
111
141
FILE *md_result_file= 0;
112
142
FILE *stderror_file= 0;
113
 
std::vector<DrizzleDumpDatabase*> database_store;
114
 
DrizzleDumpConnection* db_connection;
115
 
DrizzleDumpConnection* destination_connection;
116
 
 
117
 
enum destinations {
118
 
  DESTINATION_DB,
119
 
  DESTINATION_FILES,
120
 
  DESTINATION_STDOUT
121
 
};
122
 
 
123
 
int opt_destination= DESTINATION_STDOUT;
124
 
std::string opt_destination_host;
125
 
uint16_t opt_destination_port;
126
 
std::string opt_destination_user;
127
 
std::string opt_destination_password;
128
 
std::string opt_destination_database;
129
 
 
130
 
const string progname= "drizzledump";
131
 
 
132
 
string password,
133
 
  enclosed,
134
 
  escaped,
135
 
  current_host,
136
 
  path,
137
 
  current_user,
138
 
  opt_password,
139
 
  opt_protocol,
140
 
  where;
141
 
 
142
 
//static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
143
 
 
144
 
boost::unordered_set<string> ignore_table;
145
 
 
146
 
void maybe_exit(int error);
 
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);
147
349
static void die(int error, const char* reason, ...);
148
 
static void write_header(char *db_name);
149
 
static int dump_selected_tables(const string &db, const vector<string> &table_names);
150
 
static int dump_databases(const vector<string> &db_names);
 
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 **);
151
362
static int dump_all_databases(void);
152
 
int get_server_type();
153
 
void dump_all_tables(void);
154
 
void generate_dump(void);
155
 
void generate_dump_db(void);
156
 
 
157
 
void dump_all_tables(void)
158
 
{
159
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
160
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
161
 
  {
162
 
    if ((not (*i)->populateTables()) && (not ignore_errors))
163
 
      maybe_exit(EX_DRIZZLEERR);
164
 
  }
165
 
}
166
 
 
167
 
void generate_dump(void)
168
 
{
169
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
170
 
 
171
 
  if (path.empty())
172
 
  {
173
 
    cout << endl << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;"
174
 
      << endl << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
175
 
  }
176
 
 
177
 
  if (opt_autocommit)
178
 
    cout << "SET AUTOCOMMIT=0;" << endl;
179
 
 
180
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
181
 
  {
182
 
    DrizzleDumpDatabase *database= *i;
183
 
    cout << *database;
184
 
  }
185
 
 
186
 
  if (path.empty())
187
 
  {
188
 
    cout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;"
189
 
      << endl << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
190
 
  }
191
 
}
192
 
 
193
 
void generate_dump_db(void)
194
 
{
195
 
  std::vector<DrizzleDumpDatabase*>::iterator i;
196
 
  DrizzleStringBuf sbuf(1024);
197
 
  try
198
 
  {
199
 
    destination_connection= new DrizzleDumpConnection(opt_destination_host,
200
 
      opt_destination_port, opt_destination_user, opt_destination_password,
201
 
      false);
202
 
  }
203
 
  catch (std::exception&)
204
 
  {
205
 
    cerr << "Could not connect to destination database server" << endl;
206
 
    maybe_exit(EX_DRIZZLEERR);
207
 
  }
208
 
  sbuf.setConnection(destination_connection);
209
 
  std::ostream sout(&sbuf);
210
 
  sout.exceptions(ios_base::badbit);
211
 
 
212
 
  if (path.empty())
213
 
  {
214
 
    sout << "SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;" << endl;
215
 
    sout << "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;" << endl;
216
 
  }
217
 
 
218
 
  if (opt_autocommit)
219
 
    cout << "SET AUTOCOMMIT=0;" << endl;
220
 
 
221
 
  for (i= database_store.begin(); i != database_store.end(); ++i)
222
 
  {
223
 
    try
224
 
    {
225
 
      DrizzleDumpDatabase *database= *i;
226
 
      sout << *database;
227
 
    }
228
 
    catch (std::exception&)
229
 
    {
230
 
      std::cout << _("Error inserting into destination database") << std::endl;
231
 
      if (not ignore_errors)
232
 
        maybe_exit(EX_DRIZZLEERR);
233
 
    }
234
 
  }
235
 
 
236
 
  if (path.empty())
237
 
  {
238
 
    sout << "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;" << endl;
239
 
    sout << "SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;" << endl;
240
 
  }
 
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);
241
386
}
242
387
 
243
388
/*
254
399
    die(EX_EOF, _("Got errno %d on write"), errno);
255
400
}
256
401
 
257
 
static void write_header(char *db_name)
258
 
{
259
 
  if ((not opt_compact) and (opt_comments))
260
 
  {
261
 
    cout << "-- drizzledump " << VERSION << " libdrizzle "
262
 
      << drizzle_version() << ", for " << HOST_VENDOR << "-" << HOST_OS
263
 
      << " (" << HOST_CPU << ")" << endl << "--" << endl;
264
 
    cout << "-- Host: " << current_host << "    Database: " << db_name << endl;
265
 
    cout << "-- ------------------------------------------------------" << endl;
266
 
    cout << "-- Server version\t" << db_connection->getServerVersion();
267
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
268
 
      cout << " (MySQL server)";
269
 
    else if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_DRIZZLE_FOUND)
270
 
      cout << " (Drizzle server)";
271
 
    cout << endl << endl;
 
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);
272
476
  }
273
477
} /* write_header */
274
478
 
275
479
 
276
480
static void write_footer(FILE *sql_file)
277
481
{
278
 
  if (! opt_compact)
279
 
  {
 
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");
280
495
    if (opt_comments)
281
496
    {
282
497
      if (opt_dump_date)
283
498
      {
284
 
        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);
285
501
        fprintf(sql_file, "-- Dump completed on %s\n",
286
 
          boost::posix_time::to_simple_string(time).c_str());
 
502
                time_str);
287
503
      }
288
504
      else
289
505
        fprintf(sql_file, "-- Dump completed\n");
292
508
  }
293
509
} /* write_footer */
294
510
 
295
 
static int get_options(void)
296
 
{
 
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
 
297
686
  if (opt_single_transaction && opt_lock_all_tables)
298
687
  {
299
688
    fprintf(stderr, _("%s: You can't use --single-transaction and "
300
 
                      "--lock-all-tables at the same time.\n"), progname.c_str());
301
 
    return(EX_USAGE);
302
 
  }
303
 
  if ((opt_databases || opt_alldbs) && ! path.empty())
 
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)
304
698
  {
305
699
    fprintf(stderr,
306
700
            _("%s: --databases or --all-databases can't be used with --tab.\n"),
307
 
            progname.c_str());
 
701
            internal::my_progname);
308
702
    return(EX_USAGE);
309
703
  }
310
 
 
 
704
  if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
 
705
  {
 
706
    short_usage();
 
707
    return EX_USAGE;
 
708
  }
311
709
  if (tty_password)
312
710
    opt_password=client_get_tty_password(NULL);
313
711
  return(0);
315
713
 
316
714
 
317
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
/*
318
738
  Prints out an error message and kills the process.
319
739
 
320
740
  SYNOPSIS
335
755
  vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
336
756
  va_end(args);
337
757
 
338
 
  fprintf(stderr, "%s: %s\n", progname.c_str(), buffer);
 
758
  fprintf(stderr, "%s: %s\n", internal::my_progname, buffer);
339
759
  fflush(stderr);
340
760
 
341
761
  ignore_errors= 0; /* force the exit */
342
762
  maybe_exit(error_num);
343
763
}
344
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
 
345
878
static void free_resources(void)
346
879
{
347
880
  if (md_result_file && md_result_file != stdout)
348
881
    fclose(md_result_file);
349
 
  opt_password.erase();
 
882
  free(opt_password);
 
883
  if (defaults_argv)
 
884
    internal::free_defaults(defaults_argv);
 
885
  internal::my_end();
350
886
}
351
887
 
352
888
 
353
 
void maybe_exit(int error)
 
889
static void maybe_exit(int error)
354
890
{
355
891
  if (!first_error)
356
892
    first_error= error;
357
893
  if (ignore_errors)
358
894
    return;
359
 
  delete db_connection;
360
 
  delete destination_connection;
 
895
  drizzle_con_free(&dcon);
 
896
  drizzle_free(&drizzle);
361
897
  free_resources();
362
898
  exit(error);
363
899
}
364
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
 
365
2200
static int dump_all_databases()
366
2201
{
367
2202
  drizzle_row_t row;
368
 
  drizzle_result_st *tableres;
 
2203
  drizzle_result_st tableres;
369
2204
  int result=0;
370
 
  std::string query;
371
 
  DrizzleDumpDatabase *database;
372
 
 
373
 
  if (verbose)
374
 
    std::cerr << _("-- Retrieving database structures...") << std::endl;
375
 
 
376
 
  /* Blocking the MySQL privilege tables too because we can't import them due to bug#646187 */
377
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
378
 
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')";
379
 
  else
380
 
    query= "SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM DATA_DICTIONARY.SCHEMAS WHERE SCHEMA_NAME NOT IN ('information_schema','data_dictionary')";
381
 
 
382
 
  tableres= db_connection->query(query);
383
 
  while ((row= drizzle_row_next(tableres)))
 
2205
 
 
2206
  if (drizzleclient_query_with_error_report(&dcon, &tableres, "SHOW DATABASES", false))
 
2207
    return 1;
 
2208
  while ((row= drizzle_row_next(&tableres)))
384
2209
  {
385
 
    std::string database_name(row[0]);
386
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
387
 
      database= new DrizzleDumpDatabaseMySQL(database_name, db_connection);
388
 
    else
389
 
      database= new DrizzleDumpDatabaseDrizzle(database_name, db_connection);
390
 
 
391
 
    database->setCollate(row[1]);
392
 
    database_store.push_back(database);
 
2210
    if (dump_all_tables_in_db(row[0]))
 
2211
      result=1;
393
2212
  }
394
 
  db_connection->freeResult(tableres);
 
2213
  drizzle_result_free(&tableres);
395
2214
  return result;
396
2215
}
397
2216
/* dump_all_databases */
398
2217
 
399
2218
 
400
 
static int dump_databases(const vector<string> &db_names)
 
2219
static int dump_databases(char **db_names)
401
2220
{
402
2221
  int result=0;
403
 
  string temp;
404
 
  DrizzleDumpDatabase *database;
405
 
 
406
 
  for (vector<string>::const_iterator it= db_names.begin(); it != db_names.end(); ++it)
 
2222
  char **db;
 
2223
 
 
2224
 
 
2225
  for (db= db_names ; *db ; db++)
407
2226
  {
408
 
    temp= *it;
409
 
    if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
410
 
      database= new DrizzleDumpDatabaseMySQL(temp, db_connection);
411
 
    else
412
 
      database= new DrizzleDumpDatabaseDrizzle(temp, db_connection);
413
 
    database_store.push_back(database);
 
2227
    if (dump_all_tables_in_db(*db))
 
2228
      result=1;
414
2229
  }
415
2230
  return(result);
416
2231
} /* dump_databases */
417
2232
 
418
 
static int dump_selected_tables(const string &db, const vector<string> &table_names)
419
 
{
420
 
  DrizzleDumpDatabase *database;
421
 
 
422
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
423
 
    database= new DrizzleDumpDatabaseMySQL(db, db_connection);
424
 
  else
425
 
    database= new DrizzleDumpDatabaseDrizzle(db, db_connection);
426
 
 
427
 
  if (not database->populateTables(table_names))
428
 
  {
429
 
    delete database;
430
 
    if (not ignore_errors)
431
 
      maybe_exit(EX_DRIZZLEERR);
432
 
  }
433
 
 
434
 
  database_store.push_back(database); 
435
 
 
 
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
  }
436
2506
  return 0;
437
2507
} /* dump_selected_tables */
438
2508
 
439
 
static int do_flush_tables_read_lock()
 
2509
static int do_flush_tables_read_lock(drizzle_con_st *drizzle_con)
440
2510
{
441
2511
  /*
442
2512
    We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
446
2516
    and most client connections are stalled. Of course, if a second long
447
2517
    update starts between the two FLUSHes, we have that bad stall.
448
2518
  */
449
 
 
450
 
   db_connection->queryNoResult("FLUSH TABLES");
451
 
   db_connection->queryNoResult("FLUSH TABLES WITH READ LOCK");
452
 
 
453
 
  return 0;
454
 
}
455
 
 
456
 
static int do_unlock_tables()
457
 
{
458
 
  db_connection->queryNoResult("UNLOCK TABLES");
459
 
  return 0;
460
 
}
461
 
 
462
 
static int start_transaction()
463
 
{
464
 
  db_connection->queryNoResult("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ");
465
 
  db_connection->queryNoResult("START TRANSACTION WITH CONSISTENT SNAPSHOT");
466
 
  return 0;
467
 
}
 
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
 
468
2820
 
469
2821
int main(int argc, char **argv)
470
2822
{
471
 
try
472
 
{
473
2823
  int exit_code;
474
 
 
475
 
  po::options_description commandline_options(N_("Options used only in command line"));
476
 
  commandline_options.add_options()
477
 
  ("all-databases,A", po::value<bool>(&opt_alldbs)->default_value(false)->zero_tokens(),
478
 
  N_("Dump all the databases. This will be same as --databases with all databases selected."))
479
 
  ("all-tablespaces,Y", po::value<bool>(&opt_alltspcs)->default_value(false)->zero_tokens(),
480
 
  N_("Dump all the tablespaces."))
481
 
  ("complete-insert,c", po::value<bool>(&opt_complete_insert)->default_value(false)->zero_tokens(),
482
 
  N_("Use complete insert statements."))
483
 
  ("flush-logs,F", po::value<bool>(&flush_logs)->default_value(false)->zero_tokens(),
484
 
  N_("Flush logs file in server before starting dump. Note that if you dump many databases at once (using the option --databases= or --all-databases), the logs will be flushed for each database dumped. The exception is when using --lock-all-tables in this case the logs will be flushed only once, corresponding to the moment all tables are locked. So if you want your dump and the log flush to happen at the same exact moment you should use --lock-all-tables or --flush-logs"))
485
 
  ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
486
 
  N_("Continue even if we get an sql-error."))
487
 
  ("help,?", N_("Display this help message and exit."))
488
 
  ("lock-all-tables,x", po::value<bool>(&opt_lock_all_tables)->default_value(false)->zero_tokens(),
489
 
  N_("Locks all tables across all databases. This is achieved by taking a global read lock for the duration of the whole dump. Automatically turns --single-transaction off."))
490
 
  ("single-transaction", po::value<bool>(&opt_single_transaction)->default_value(false)->zero_tokens(),
491
 
  N_("Creates a consistent snapshot by dumping all tables in a single transaction. Works ONLY for tables stored in storage engines which support multiversioning (currently only InnoDB does); the dump is NOT guaranteed to be consistent for other storage engines. While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents), no other connection should use the following statements: ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not isolated from them."))
492
 
  ("skip-opt", 
493
 
  N_("Disable --opt. Disables --add-drop-table, --add-locks, --create-options, ---extended-insert and --disable-keys."))    
494
 
  ("tables", N_("Overrides option --databases (-B)."))
495
 
  ("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(10000),
496
 
  N_("Number of rows before each output progress report (requires --verbose)."))
497
 
  ("verbose,v", po::value<bool>(&verbose)->default_value(false)->zero_tokens(),
498
 
  N_("Print info about the various stages."))
499
 
  ("version,V", N_("Output version information and exit."))
500
 
  ("skip-comments", N_("Turn off Comments"))
501
 
  ("skip-create", N_("Turn off create-options"))
502
 
  ("skip-extended-insert", N_("Turn off extended-insert"))
503
 
  ("skip-dump-date",N_( "Turn off dump date at the end of the output"))
504
 
  ("no-defaults", N_("Do not read from the configuration files"))
505
 
  ;
506
 
 
507
 
  po::options_description dump_options(N_("Options specific to the drizzle client"));
508
 
  dump_options.add_options()
509
 
  ("add-drop-database", po::value<bool>(&opt_drop_database)->default_value(false)->zero_tokens(),
510
 
  N_("Add a 'DROP DATABASE' before each create."))
511
 
  ("skip-drop-table", N_("Do not add a 'drop table' before each create."))
512
 
  ("compact", po::value<bool>(&opt_compact)->default_value(false)->zero_tokens(),
513
 
  N_("Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs.  Enables options --skip-add-drop-table --no-set-names --skip-disable-keys"))
514
 
  ("databases,B", po::value<bool>(&opt_databases)->default_value(false)->zero_tokens(),
515
 
  N_("To dump several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames. 'USE db_name;' will be included in the output."))
516
 
  ("skip-disable-keys,K",
517
 
  N_("'ALTER TABLE tb_name DISABLE KEYS; and 'ALTER TABLE tb_name ENABLE KEYS; will not be put in the output."))
518
 
  ("ignore-table", po::value<string>(),
519
 
  N_("Do not dump the specified table. To specify more than one table to ignore, use the directive multiple times, once for each table.  Each table must be specified with both database and table names, e.g. --ignore-table=database.table"))
520
 
  ("insert-ignore", po::value<bool>(&opt_ignore)->default_value(false)->zero_tokens(),
521
 
  N_("Insert rows with INSERT IGNORE."))
522
 
  ("no-autocommit", po::value<bool>(&opt_autocommit)->default_value(false)->zero_tokens(),
523
 
  N_("Wrap a table's data in START TRANSACTION/COMMIT statements."))
524
 
  ("no-create-db,n", po::value<bool>(&opt_create_db)->default_value(false)->zero_tokens(),
525
 
  N_("'CREATE DATABASE IF NOT EXISTS db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given."))
526
 
  ("no-data,d", po::value<bool>(&opt_no_data)->default_value(false)->zero_tokens(),
527
 
  N_("No row information."))
528
 
  ("replace", po::value<bool>(&opt_replace_into)->default_value(false)->zero_tokens(),
529
 
  N_("Use REPLACE INTO instead of INSERT INTO."))
530
 
  ("destination-type", po::value<string>()->default_value("stdout"),
531
 
  N_("Where to send output to (stdout|database"))
532
 
  ("destination-host", po::value<string>(&opt_destination_host)->default_value("localhost"),
533
 
  N_("Hostname for destination db server (requires --destination-type=database)"))
534
 
  ("destination-port", po::value<uint16_t>(&opt_destination_port)->default_value(4427),
535
 
  N_("Port number for destination db server (requires --destination-type=database)"))
536
 
  ("destination-user", po::value<string>(&opt_destination_user),
537
 
  N_("User name for destination db server (resquires --destination-type=database)"))
538
 
  ("destination-password", po::value<string>(&opt_destination_password),
539
 
  N_("Password for destination db server (requires --destination-type=database)"))
540
 
  ("destination-database", po::value<string>(&opt_destination_database),
541
 
  N_("The database in the destination db server (requires --destination-type=database, not for use with --all-databases)"))
542
 
  ;
543
 
 
544
 
  po::options_description client_options(N_("Options specific to the client"));
545
 
  client_options.add_options()
546
 
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
547
 
  N_("Connect to host."))
548
 
  ("password,P", po::value<string>(&password)->default_value(PASSWORD_SENTINEL),
549
 
  N_("Password to use when connecting to server. If password is not given it's solicited on the tty."))
550
 
  ("port,p", po::value<uint32_t>(&opt_drizzle_port)->default_value(0),
551
 
  N_("Port number to use for connection."))
552
 
  ("user,u", po::value<string>(&current_user)->default_value(""),
553
 
  N_("User for login if not current user."))
554
 
  ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
555
 
  N_("The protocol of connection (mysql or drizzle)."))
556
 
  ;
557
 
 
558
 
  po::options_description hidden_options(N_("Hidden Options"));
559
 
  hidden_options.add_options()
560
 
  ("database-used", po::value<vector<string> >(), N_("Used to select the database"))
561
 
  ("Table-used", po::value<vector<string> >(), N_("Used to select the tables"))
562
 
  ;
563
 
 
564
 
  po::options_description all_options(N_("Allowed Options + Hidden Options"));
565
 
  all_options.add(commandline_options).add(dump_options).add(client_options).add(hidden_options);
566
 
 
567
 
  po::options_description long_options(N_("Allowed Options"));
568
 
  long_options.add(commandline_options).add(dump_options).add(client_options);
569
 
 
570
 
  std::string system_config_dir_dump(SYSCONFDIR); 
571
 
  system_config_dir_dump.append("/drizzle/drizzledump.cnf");
572
 
 
573
 
  std::string system_config_dir_client(SYSCONFDIR); 
574
 
  system_config_dir_client.append("/drizzle/client.cnf");
575
 
 
576
 
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
577
 
 
578
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
579
 
  {
580
 
    char *homedir;
581
 
    homedir= getenv("HOME");
582
 
    if (homedir != NULL)
583
 
      user_config_dir.replace(0, 1, homedir);
584
 
  }
585
 
 
586
 
  po::positional_options_description p;
587
 
  p.add("database-used", 1);
588
 
  p.add("Table-used",-1);
589
 
 
590
 
  md_result_file= stdout;
591
 
 
592
 
  po::variables_map vm;
593
 
 
594
 
  // Disable allow_guessing
595
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
596
 
 
597
 
  po::store(po::command_line_parser(argc, argv).style(style).
598
 
            options(all_options).positional(p).
599
 
            extra_parser(parse_password_arg).run(), vm);
600
 
 
601
 
  if (! vm.count("no-defaults"))
602
 
  {
603
 
    std::string user_config_dir_dump(user_config_dir);
604
 
    user_config_dir_dump.append("/drizzle/drizzledump.cnf"); 
605
 
 
606
 
    std::string user_config_dir_client(user_config_dir);
607
 
    user_config_dir_client.append("/drizzle/client.cnf");
608
 
 
609
 
    ifstream user_dump_ifs(user_config_dir_dump.c_str());
610
 
    po::store(parse_config_file(user_dump_ifs, dump_options), vm);
611
 
 
612
 
    ifstream user_client_ifs(user_config_dir_client.c_str());
613
 
    po::store(parse_config_file(user_client_ifs, client_options), vm);
614
 
 
615
 
    ifstream system_dump_ifs(system_config_dir_dump.c_str());
616
 
    po::store(parse_config_file(system_dump_ifs, dump_options), vm);
617
 
 
618
 
    ifstream system_client_ifs(system_config_dir_client.c_str());
619
 
    po::store(parse_config_file(system_client_ifs, client_options), vm);
620
 
  }
621
 
 
622
 
  po::notify(vm);  
623
 
  
624
 
  if ((not vm.count("database-used") && not vm.count("Table-used") 
625
 
    && not opt_alldbs && path.empty())
626
 
    || (vm.count("help")) || vm.count("version"))
627
 
  {
628
 
    printf(_("Drizzledump %s build %s, for %s-%s (%s)\n"),
629
 
      drizzle_version(), VERSION, HOST_VENDOR, HOST_OS, HOST_CPU);
630
 
    if (vm.count("version"))
631
 
      exit(0);
632
 
    puts("");
633
 
    puts(_("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"));
634
 
    puts(_("Dumps definitions and data from a Drizzle database server"));
635
 
    printf(_("Usage: %s [OPTIONS] database [tables]\n"), progname.c_str());
636
 
    printf(_("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n"),
637
 
          progname.c_str());
638
 
    printf(_("OR     %s [OPTIONS] --all-databases [OPTIONS]\n"), progname.c_str());
639
 
    cout << long_options;
640
 
    if (vm.count("help"))
641
 
      exit(0);
642
 
    else
643
 
      exit(1);
644
 
  }
645
 
 
646
 
  /* Inverted Booleans */
647
 
 
648
 
  opt_drop= (vm.count("skip-drop-table")) ? false : true;
649
 
  opt_comments= (vm.count("skip-comments")) ? false : true;
650
 
  extended_insert= (vm.count("skip-extended-insert")) ? false : true;
651
 
  opt_dump_date= (vm.count("skip-dump-date")) ? false : true;
652
 
  opt_disable_keys= (vm.count("skip-disable-keys")) ? false : true;
653
 
  opt_quoted= (vm.count("skip-quote-names")) ? false : true;
654
 
 
655
 
  if (vm.count("protocol"))
656
 
  {
657
 
    std::transform(opt_protocol.begin(), opt_protocol.end(),
658
 
      opt_protocol.begin(), ::tolower);
659
 
 
660
 
    if (not opt_protocol.compare("mysql"))
661
 
      use_drizzle_protocol=false;
662
 
    else if (not opt_protocol.compare("drizzle"))
663
 
      use_drizzle_protocol=true;
664
 
    else
665
 
    {
666
 
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
667
 
      exit(-1);
668
 
    }
669
 
  }
670
 
 
671
 
  if (vm.count("port"))
672
 
  {
673
 
    /* If the port number is > 65535 it is not a valid port
674
 
     *        This also helps with potential data loss casting unsigned long to a
675
 
     *               uint32_t. 
676
 
     */
677
 
    if (opt_drizzle_port > 65535)
678
 
    {
679
 
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
680
 
      exit(-1);
681
 
    }
682
 
  }
683
 
 
684
 
  if(vm.count("password"))
685
 
  {
686
 
    if (!opt_password.empty())
687
 
      opt_password.erase();
688
 
    if (password == PASSWORD_SENTINEL)
689
 
    {
690
 
      opt_password= "";
691
 
    }
692
 
    else
693
 
    {
694
 
      opt_password= password;
695
 
      tty_password= false;
696
 
    }
697
 
  }
698
 
  else
699
 
  {
700
 
      tty_password= true;
701
 
  }
702
 
 
703
 
  if (! path.empty())
704
 
  { 
705
 
    opt_disable_keys= 0;
706
 
  }
707
 
 
708
 
  if (vm.count("skip-opt"))
709
 
  {
710
 
    extended_insert= opt_drop= create_options= 0;
711
 
    opt_disable_keys= 0;
712
 
  }
713
 
 
714
 
  if (opt_compact)
715
 
  { 
716
 
    opt_comments= opt_drop= opt_disable_keys= 0;
717
 
  }
718
 
 
719
 
  if (vm.count("opt"))
720
 
  {
721
 
    extended_insert= opt_drop= create_options= 1;
722
 
    opt_disable_keys= 1;
723
 
  }
724
 
 
725
 
  if (vm.count("tables"))
726
 
  { 
727
 
    opt_databases= false;
728
 
  }
729
 
 
730
 
  if (vm.count("ignore-table"))
731
 
  {
732
 
    if (!strchr(vm["ignore-table"].as<string>().c_str(), '.'))
733
 
    {
734
 
      fprintf(stderr, _("Illegal use of option --ignore-table=<database>.<table>\n"));
735
 
      exit(EXIT_ARGUMENT_INVALID);
736
 
    }
737
 
    string tmpptr(vm["ignore-table"].as<string>());
738
 
    ignore_table.insert(tmpptr); 
739
 
  }
740
 
 
741
 
  if (vm.count("skip-create"))
742
 
  {
743
 
    opt_create_db= opt_no_create_info= create_options= false;
744
 
  }
745
 
 
746
 
  exit_code= get_options();
 
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);
747
2830
  if (exit_code)
748
2831
  {
749
2832
    free_resources();
750
2833
    exit(exit_code);
751
2834
  }
752
 
  try
753
 
  {
754
 
    db_connection = new DrizzleDumpConnection(current_host, opt_drizzle_port,
755
 
      current_user, opt_password, use_drizzle_protocol);
756
 
  }
757
 
  catch (std::exception&)
758
 
  {
759
 
    maybe_exit(EX_DRIZZLEERR);
760
 
  }
761
 
 
762
 
  if (db_connection->getServerType() == DrizzleDumpConnection::SERVER_MYSQL_FOUND)
763
 
    db_connection->queryNoResult("SET NAMES 'utf8'");
764
 
 
765
 
  if (vm.count("destination-type"))
766
 
  {
767
 
    string tmp_destination(vm["destination-type"].as<string>());
768
 
    if (tmp_destination.compare("database") == 0)
769
 
      opt_destination= DESTINATION_DB;
770
 
    else if (tmp_destination.compare("stdout") == 0)
771
 
      opt_destination= DESTINATION_STDOUT;
772
 
    else
773
 
      exit(EXIT_ARGUMENT_INVALID);
774
 
  }
775
 
 
776
 
 
777
 
  if (path.empty() && vm.count("database-used"))
778
 
  {
779
 
    string database_used= *vm["database-used"].as< vector<string> >().begin();
780
 
    write_header((char *)database_used.c_str());
781
 
  }
782
 
 
783
 
  if ((opt_lock_all_tables) && do_flush_tables_read_lock())
 
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))
784
2845
    goto err;
785
 
  if (opt_single_transaction && start_transaction())
 
2846
  if (opt_single_transaction && start_transaction(&dcon))
786
2847
    goto err;
787
2848
  if (opt_lock_all_tables)
788
 
    db_connection->queryNoResult("FLUSH LOGS");
789
 
  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! */
790
2856
    goto err;
791
2857
 
792
2858
  if (opt_alldbs)
793
2859
  {
794
2860
    dump_all_databases();
795
 
    dump_all_tables();
796
2861
  }
797
 
  if (vm.count("database-used") && vm.count("Table-used") && ! opt_databases)
 
2862
  else if (argc > 1 && !opt_databases)
798
2863
  {
799
 
    string database_used= *vm["database-used"].as< vector<string> >().begin();
800
2864
    /* Only one database and selected table(s) */
801
 
    dump_selected_tables(database_used, vm["Table-used"].as< vector<string> >());
802
 
  }
803
 
 
804
 
  if (vm.count("Table-used") and opt_databases)
805
 
  {
806
 
    vector<string> database_used= vm["database-used"].as< vector<string> >();
807
 
    vector<string> table_used= vm["Table-used"].as< vector<string> >();
808
 
 
809
 
    for (vector<string>::iterator it= table_used.begin();
810
 
       it != table_used.end();
811
 
       ++it)
812
 
    {
813
 
      database_used.insert(database_used.end(), *it);
814
 
    }
815
 
 
816
 
    dump_databases(database_used);
817
 
    dump_all_tables();
818
 
  }
819
 
 
820
 
  if (vm.count("database-used") && ! vm.count("Table-used"))
821
 
  {
822
 
    dump_databases(vm["database-used"].as< vector<string> >());
823
 
    dump_all_tables();
824
 
  }
825
 
 
826
 
  if (opt_destination == DESTINATION_STDOUT)
827
 
    generate_dump();
 
2865
    dump_selected_tables(*argv, (argv + 1), (argc - 1));
 
2866
  }
828
2867
  else
829
 
    generate_dump_db();
 
2868
  {
 
2869
    dump_databases(argv);
 
2870
  }
830
2871
 
831
2872
  /* ensure dumped data flushed */
832
2873
  if (md_result_file && fflush(md_result_file))
843
2884
    server.
844
2885
  */
845
2886
err:
846
 
  delete db_connection;
847
 
  delete destination_connection;
848
 
  if (path.empty())
 
2887
  dbDisconnect(current_host);
 
2888
  if (!path)
849
2889
    write_footer(md_result_file);
850
2890
  free_resources();
851
2891
 
852
2892
  if (stderror_file)
853
2893
    fclose(stderror_file);
854
 
}
855
2894
 
856
 
  catch(exception &err)
857
 
  {
858
 
    cerr << err.what() << endl;
859
 
  }
860
 
  
861
2895
  return(first_error);
862
2896
} /* main */