~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzledump.cc

  • Committer: devananda
  • Date: 2009-07-01 17:38:47 UTC
  • mto: (1093.1.7 captain)
  • mto: This revision was merged to the branch mainline in revision 1095.
  • Revision ID: devananda.vdv@gmail.com-20090701173847-3n3mbtessg5ff35e
refactored function/benchmark into plugin/benchmark

Show diffs side-by-side

added added

removed removed

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