~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: Mark Atwood
  • Date: 2010-06-24 03:15:21 UTC
  • mto: (1637.2.4 build)
  • mto: This revision was merged to the branch mainline in revision 1639.
  • Revision ID: me@mark.atwood.name-20100624031521-gafmppfbf5afm68w
new syslog module, with plugins for query log, error message, and SYSLOG() function

Show diffs side-by-side

added added

removed removed

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