mysqldump.c 122 KB
Newer Older
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
1
/* Copyright (C) 2000 MySQL AB
2

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3 4
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6

bk@work.mysql.com's avatar
bk@work.mysql.com committed
7 8 9 10
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
11

bk@work.mysql.com's avatar
bk@work.mysql.com committed
12 13 14 15 16 17 18 19
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* mysqldump.c  - Dump a tables contents and format to an ASCII file
**
** The author's original notes follow :-
**
20 21 22
** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
** DATE:   December 3, 1994
** WARRANTY: None, expressed, impressed, implied
23
**          or other
24 25 26 27 28 29 30 31
** STATUS: Public domain
** Adapted and optimized for MySQL by
** Michael Widenius, Sinisa Milivojevic, Jani Tolonen
** -w --where added 9/10/98 by Jim Faucette
** slave code by David Saez Padros <david@ols.es>
** master/autocommit code by Brian Aker <brian@tangent.org>
** SSL by
** Andrei Errapart <andreie@no.spam.ee>
32
** Tõnu Samuel  <tonu@please.do.not.remove.this.spam.ee>
33 34
** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up
** and adapted to mysqldump 05/11/01 by Jani Tolonen
35
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
36
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
37
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
38

39
#define DUMP_VERSION "10.11"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
40

41
#include <my_global.h>
bk@work.mysql.com's avatar
bk@work.mysql.com committed
42
#include <my_sys.h>
43
#include <my_user.h>
bk@work.mysql.com's avatar
bk@work.mysql.com committed
44 45
#include <m_string.h>
#include <m_ctype.h>
46
#include <hash.h>
47
#include <stdarg.h>
bk@work.mysql.com's avatar
bk@work.mysql.com committed
48

49
#include "client_priv.h"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
50 51 52 53 54 55 56 57 58 59
#include "mysql.h"
#include "mysql_version.h"
#include "mysqld_error.h"

/* Exit codes */

#define EX_USAGE 1
#define EX_MYSQLERR 2
#define EX_CONSCHECK 3
#define EX_EOM 4
60
#define EX_EOF 5 /* ferror for output file was got */
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
61
#define EX_ILLEGAL_TABLE 6
bk@work.mysql.com's avatar
bk@work.mysql.com committed
62 63 64 65 66 67 68 69 70

/* index into 'show fields from table' */

#define SHOW_FIELDNAME  0
#define SHOW_TYPE  1
#define SHOW_NULL  2
#define SHOW_DEFAULT  4
#define SHOW_EXTRA  5

71 72 73
/* Size of buffer for dump's select query */
#define QUERY_LENGTH 1536

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
74 75 76 77 78
/* ignore table flags */
#define IGNORE_NONE 0x00 /* no ignore */
#define IGNORE_DATA 0x01 /* don't dump data for this table */
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */

79 80
static void add_load_option(DYNAMIC_STRING *str, const char *option,
                             const char *option_value);
81
static ulong find_set(TYPELIB *lib, const char *x, uint length,
82
                      char **err_pos, uint *err_len);
83
static char *alloc_query_str(ulong size);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
84

85
static void field_escape(DYNAMIC_STRING* in, const char *from);
86 87
static my_bool  verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
                quick= 1, extended_insert= 1,
88
                lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0,
89
                opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
90
                opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
jimw@mysql.com's avatar
jimw@mysql.com committed
91
                opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
92
                opt_set_charset=0, opt_dump_date=1,
93 94 95 96
                opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
                opt_delete_master_logs=0, tty_password=0,
                opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
                opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
97
                opt_complete_insert= 0, opt_drop_database= 0,
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
98
                opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1;
99
static ulong opt_max_allowed_packet, opt_net_buffer_length;
100
static MYSQL mysql_connection,*mysql=0;
101
static my_bool insert_pat_inited= 0, info_flag;
102 103
static DYNAMIC_STRING insert_pat;
static char  *opt_password=0,*current_user=0,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
104 105
             *current_host=0,*path=0,*fields_terminated=0,
             *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
106
             *where=0, *order_by=0,
107
             *opt_compatible_mode_str= 0,
108 109
             *err_ptr= 0,
             *log_error_file= NULL;
110
static char **defaults_argv= 0;
111
static char compatible_mode_normal_str[255];
112
static ulong opt_compatible_mode= 0;
113 114
#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
115
static uint     opt_mysql_port= 0, opt_master_data;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
116 117 118
static my_string opt_mysql_unix_port=0;
static int   first_error=0;
static DYNAMIC_STRING extended_row;
119
#include <sslopt-vars.h>
120 121 122
FILE *md_result_file= 0;
FILE *stderror_file=0;

123 124 125
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
#endif
126
static uint opt_protocol= 0;
127 128 129 130 131 132 133 134 135 136 137 138 139

/*
Dynamic_string wrapper functions. In this file use these
wrappers, they will terminate the process if there is
an allocation failure.
*/
static void init_dynamic_string_checked(DYNAMIC_STRING *str, const char *init_str,
			    uint init_alloc, uint alloc_increment);
static void dynstr_append_checked(DYNAMIC_STRING* dest, const char* src);
static void dynstr_set_checked(DYNAMIC_STRING *str, const char *init_str);
static void dynstr_append_mem_checked(DYNAMIC_STRING *str, const char *append,
			  uint length);
static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size);
140
/*
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
141 142 143
  Constant for detection of default value of default_charset.
  If default_charset is equal to mysql_universal_client_charset, then
  it is the default value which assigned at the very beginning of main().
144
*/
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
145
static const char *mysql_universal_client_charset=
146 147
  MYSQL_UNIVERSAL_CLIENT_CHARSET;
static char *default_charset;
148
static CHARSET_INFO *charset_info= &my_charset_latin1;
149
const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace";
150 151
/* have we seen any VIEWs during table scanning? */
my_bool seen_views= 0;
152 153 154 155

const char *compatible_mode_names[]=
{
  "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
156 157
  "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
  "ANSI",
158 159
  NullS
};
160 161 162 163 164 165 166 167 168
#define MASK_ANSI_QUOTES \
(\
 (1<<2)  | /* POSTGRESQL */\
 (1<<3)  | /* ORACLE     */\
 (1<<4)  | /* MSSQL      */\
 (1<<5)  | /* DB2        */\
 (1<<6)  | /* MAXDB      */\
 (1<<10)   /* ANSI       */\
)
169
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
170
                                  "", compatible_mode_names, NULL};
171

172
HASH ignore_table;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
173

174
static struct my_option my_long_options[] =
bk@work.mysql.com's avatar
bk@work.mysql.com committed
175
{
176 177 178
  {"all", 'a', "Deprecated. Use --create-options instead.",
   (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
   0, 0, 0, 0, 0},
179 180 181 182
  {"all-databases", 'A',
   "Dump all the databases. This will be same as --databases with all databases selected.",
   (gptr*) &opt_alldbs, (gptr*) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
183 184 185
  {"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
   (gptr*) &opt_drop_database, (gptr*) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
   0},
186
  {"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
187
   (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
188 189
   0},
  {"add-locks", OPT_LOCKS, "Add locks around insert statements.",
190
   (gptr*) &opt_lock, (gptr*) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
191 192 193 194
   0},
  {"allow-keywords", OPT_KEYWORDS,
   "Allow creation of column names that are keywords.", (gptr*) &opt_keywords,
   (gptr*) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
195
#ifdef __NETWARE__
196
  {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
197 198
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
199
  {"character-sets-dir", OPT_CHARSETS_DIR,
200
   "Directory where character sets are.", (gptr*) &charsets_dir,
201
   (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
paul@kite-hub.kitebird.com's avatar
paul@kite-hub.kitebird.com committed
202 203 204
  {"comments", 'i', "Write additional information.",
   (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
   1, 0, 0, 0, 0, 0},
205
  {"compatible", OPT_COMPATIBLE,
monty@mishka.local's avatar
monty@mishka.local committed
206
   "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 MySQL server version 4.1.0 or higher. This option is ignored with earlier server versions.",
207 208
   (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0,
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
209
  {"compact", OPT_COMPACT,
serg@serg.mylan's avatar
serg@serg.mylan committed
210
   "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",
211 212
   (gptr*) &opt_compact, (gptr*) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
213 214 215
  {"complete-insert", 'c', "Use complete insert statements.",
   (gptr*) &opt_complete_insert, (gptr*) &opt_complete_insert, 0, GET_BOOL,
   NO_ARG, 0, 0, 0, 0, 0, 0},
216 217 218
  {"compress", 'C', "Use compression in server/client protocol.",
   (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
   0, 0, 0},
monty@mishka.local's avatar
monty@mishka.local committed
219 220 221 222
  {"create-options", OPT_CREATE_OPTIONS,
   "Include all MySQL specific create options.",
   (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
   0, 0, 0, 0, 0},
223 224 225 226
  {"databases", 'B',
   "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.",
   (gptr*) &opt_databases, (gptr*) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
   0, 0, 0, 0},
227 228 229 230 231 232 233
#ifdef DBUG_OFF
  {"debug", '#', "This is a non-debug version. Catch this and exit",
   0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
#else
  {"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
   (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
234 235
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", (gptr*) &info_flag,
   (gptr*) &info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
236 237 238
  {"default-character-set", OPT_DEFAULT_CHARSET,
   "Set the default character set.", (gptr*) &default_charset,
   (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
239
  {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
240 241
   (gptr*) &opt_delayed, (gptr*) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
242
  {"delete-master-logs", OPT_DELETE_MASTER_LOGS,
243 244 245
   "Delete logs on master after backup. This automatically enables --master-data.",
   (gptr*) &opt_delete_master_logs, (gptr*) &opt_delete_master_logs, 0,
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
246 247
  {"disable-keys", 'K',
   "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (gptr*) &opt_disable_keys,
248
   (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
249 250 251
  {"extended-insert", 'e',
   "Allows utilization of the new, much faster INSERT syntax.",
   (gptr*) &extended_insert, (gptr*) &extended_insert, 0, GET_BOOL, NO_ARG,
252
   1, 0, 0, 0, 0, 0},
253 254 255 256 257 258 259 260 261 262
  {"fields-terminated-by", OPT_FTB,
   "Fields in the textfile are terminated by ...", (gptr*) &fields_terminated,
   (gptr*) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"fields-enclosed-by", OPT_ENC,
   "Fields in the importfile are enclosed by ...", (gptr*) &enclosed,
   (gptr*) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
  {"fields-optionally-enclosed-by", OPT_O_ENC,
   "Fields in the i.file are opt. enclosed by ...", (gptr*) &opt_enclosed,
   (gptr*) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
  {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
serg@serg.mylan's avatar
serg@serg.mylan committed
263
   (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
264 265
  {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
   (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
266
   0, 0, 0, 0, 0, 0},
serg@serg.mylan's avatar
serg@serg.mylan committed
267
  {"flush-logs", 'F', "Flush logs file in server before starting dump. "
268 269 270 271 272 273 274 275
   "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 "
   "or --master-data: "
   "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 --master-data with --flush-logs",
276 277
   (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
278 279 280 281 282 283
  {"flush-privileges", OPT_ESC, "Emit a FLUSH PRIVILEGES statement "
   "after dumping the mysql database.  This option should be used any "
   "time the dump contains the mysql database and any other database "
   "that depends on the data in the mysql database for proper restore. ",
   (gptr*) &flush_privileges, (gptr*) &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
284 285 286 287 288
  {"force", 'f', "Continue even if we get an sql-error.",
   (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG,
   0, 0, 0, 0, 0, 0},
  {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
   NO_ARG, 0, 0, 0, 0, 0, 0},
paul@kite-hub.kitebird.com's avatar
paul@kite-hub.kitebird.com committed
289 290 291
  {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
    "VARBINARY, BLOB) in hexadecimal format.",
   (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
292
  {"host", 'h', "Connect to host.", (gptr*) &current_host,
293
   (gptr*) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
294 295 296 297 298
  {"ignore-table", OPT_IGNORE_TABLE,
   "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",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
299 300 301
  {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
   (gptr*) &opt_ignore, (gptr*) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
302 303 304
  {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
   (gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR,
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
305
  {"lock-all-tables", 'x', "Locks all tables across all databases. This "
306 307 308 309
   "is achieved by taking a global read lock for the duration of the whole "
   "dump. Automatically turns --single-transaction and --lock-tables off.",
   (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
   0, 0, 0, 0, 0, 0},
310
  {"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables,
311
   (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
312 313 314
  {"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.",
   (gptr*) &log_error_file, (gptr*) &log_error_file, 0, GET_STR,
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
315
  {"master-data", OPT_MASTER_DATA,
316 317 318 319 320 321 322 323 324 325
   "This causes the binary log position and filename to be appended to the "
   "output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
   " to 2, that command will be prefixed with a comment symbol. "
   "This option will turn --lock-all-tables on, unless "
   "--single-transaction is specified too (in which case a "
   "global read lock is only taken a short time at the beginning of the dump "
   "- don't forget to read about --single-transaction below). In all cases "
   "any action on logs will happen at the exact moment of the dump."
   "Option automatically turns --lock-tables off.",
   (gptr*) &opt_master_data, (gptr*) &opt_master_data, 0,
326
   GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
monty@mysql.com's avatar
monty@mysql.com committed
327 328
  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
    (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0,
329
    GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
monty@mysql.com's avatar
monty@mysql.com committed
330 331 332 333 334
   (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
  {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
    (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0,
    GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
   MALLOC_OVERHEAD-1024, 1024, 0},
335 336 337 338 339
  {"no-autocommit", OPT_AUTOCOMMIT,
   "Wrap tables with autocommit/commit statements.",
   (gptr*) &opt_autocommit, (gptr*) &opt_autocommit, 0, GET_BOOL, NO_ARG,
   0, 0, 0, 0, 0, 0},
  {"no-create-db", 'n',
340
   "'CREATE DATABASE /*!32312 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.}.",
341 342 343
   (gptr*) &opt_create_db, (gptr*) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
   0, 0, 0, 0},
  {"no-create-info", 't', "Don't write table creation info.",
344 345 346 347
   (gptr*) &opt_no_create_info, (gptr*) &opt_no_create_info, 0, GET_BOOL,
   NO_ARG, 0, 0, 0, 0, 0, 0},
  {"no-data", 'd', "No row information.", (gptr*) &opt_no_data,
   (gptr*) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
348
  {"no-set-names", 'N',
349
   "Deprecated. Use --skip-set-charset instead.",
350
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
351
  {"opt", OPT_OPTIMIZE,
352
   "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.",
353
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
paul@kite-hub.kitebird.com's avatar
paul@kite-hub.kitebird.com committed
354 355 356
  {"order-by-primary", OPT_ORDER_BY_PRIMARY,
   "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.",
   (gptr*) &opt_order_by_primary, (gptr*) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
357 358 359
  {"password", 'p',
   "Password to use when connecting to server. If password is not given it's solicited on the tty.",
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
bk@work.mysql.com's avatar
bk@work.mysql.com committed
360
#ifdef __WIN__
361
  {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
362
   NO_ARG, 0, 0, 0, 0, 0, 0},
bk@work.mysql.com's avatar
bk@work.mysql.com committed
363
#endif
364
  {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
365
   (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
366
   0},
367
  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
368
   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
369
  {"quick", 'q', "Don't buffer query, dump directly to stdout.",
370
   (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
371
  {"quote-names",'Q', "Quote table and column names with backticks (`).",
372
   (gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
373 374
   0, 0},
  {"result-file", 'r',
serg@sergbook.mysql.com's avatar
serg@sergbook.mysql.com committed
375
   "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).",
376
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
paul@frost.snake.net's avatar
paul@frost.snake.net committed
377
  {"routines", 'R', "Dump stored routines (functions and procedures).",
378 379
     (gptr*) &opt_routines, (gptr*) &opt_routines, 0, GET_BOOL,
     NO_ARG, 0, 0, 0, 0, 0, 0},
monty@mysql.com's avatar
monty@mysql.com committed
380 381 382 383
  {"set-charset", OPT_SET_CHARSET,
   "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
   (gptr*) &opt_set_charset, (gptr*) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
   0, 0, 0, 0, 0},
384 385 386
  {"set-variable", 'O',
   "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
387
#ifdef HAVE_SMEM
388
  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
389
   "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
390 391
   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
monty@mysql.com's avatar
monty@mysql.com committed
392 393 394 395 396
  /*
    Note that the combination --single-transaction --master-data
    will give bullet-proof binlog position only if server >=4.1.3. That's the
    old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug.
  */
397
  {"single-transaction", OPT_TRANSACTION,
monty@mysql.com's avatar
monty@mysql.com committed
398 399 400 401 402 403 404
   "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. Option "
   "automatically turns off --lock-tables.",
   (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0,
   GET_BOOL, NO_ARG,  0, 0, 0, 0, 0, 0},
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
405 406 407
  {"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.",
   (gptr*) &opt_dump_date, (gptr*) &opt_dump_date, 0,
   GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
408
  {"skip-opt", OPT_SKIP_OPTIMIZATION,
409
   "Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
410
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
411 412 413
  {"socket", 'S', "Socket file to use for connection.",
   (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
414
#include <sslopt-longopts.h>
415 416 417 418 419
  {"tab",'T',
   "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.",
   (gptr*) &path, (gptr*) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"tables", OPT_TABLES, "Overrides option --databases (-B).",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
420
   {"triggers", OPT_TRIGGERS, "Dump triggers for each dumped table",
421 422
     (gptr*) &opt_dump_triggers, (gptr*) &opt_dump_triggers, 0, GET_BOOL,
     NO_ARG, 1, 0, 0, 0, 0, 0},
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
423
  {"tz-utc", OPT_TZ_UTC,
424
    "SET TIME_ZONE='+00:00' at top of dump to allow dumping of TIMESTAMP data when a server has data in different time zones or data is being moved between servers with different time zones.",
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
425
    (gptr*) &opt_tz_utc, (gptr*) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
bk@work.mysql.com's avatar
bk@work.mysql.com committed
426
#ifndef DONT_ALLOW_USER_CHANGE
427 428 429
  {"user", 'u', "User for login if not current user.",
   (gptr*) &current_user, (gptr*) &current_user, 0, GET_STR, REQUIRED_ARG,
   0, 0, 0, 0, 0, 0},
bk@work.mysql.com's avatar
bk@work.mysql.com committed
430
#endif
431 432 433 434 435 436 437 438
  {"verbose", 'v', "Print info about the various stages.",
   (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"version",'V', "Output version information and exit.", 0, 0, 0,
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"where", 'w', "Dump only selected records; QUOTES mandatory!",
   (gptr*) &where, (gptr*) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
   NO_ARG, 0, 0, 0, 0, 0, 0},
439
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
440 441 442 443
};

static const char *load_default_groups[]= { "mysqldump","client",0 };

444 445 446
static void maybe_exit(int error);
static void die(int error, const char* reason, ...);
static void maybe_die(int error, const char* reason, ...);
447
static void write_header(FILE *sql_file, char *db_name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
448
static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
449 450
                        const char *prefix,const char *name,
                        int string_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
451 452
static int dump_selected_tables(char *db, char **table_names, int tables);
static int dump_all_tables_in_db(char *db);
453 454 455
static int init_dumping_views(char *);
static int init_dumping_tables(char *);
static int init_dumping(char *, int init_func(char*));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
456 457
static int dump_databases(char **);
static int dump_all_databases();
458
static char *quote_name(const char *name, char *buff, my_bool force);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
459
char check_if_ignore_table(const char *table_name, char *table_type);
460
static char *primary_key_fields(const char *table_name);
461
static my_bool get_view_structure(char *table, char* db);
462
static my_bool dump_all_views_in_db(char *database);
463

monty@mysql.com's avatar
monty@mysql.com committed
464
#include <help_start.h>
bk@work.mysql.com's avatar
bk@work.mysql.com committed
465

466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
/*
  Print the supplied message if in verbose mode

  SYNOPSIS
    verbose_msg()
    fmt   format specifier
    ...   variable number of parameters
*/

static void verbose_msg(const char *fmt, ...)
{
  va_list args;
  DBUG_ENTER("verbose_msg");

  if (!verbose)
    DBUG_VOID_RETURN;

  va_start(args, fmt);
  vfprintf(stderr, fmt, args);
  va_end(args);

  DBUG_VOID_RETURN;
}

490 491
/*
  exit with message if ferror(file)
492

493 494
  SYNOPSIS
    check_io()
495
    file        - checked file
496 497 498 499 500
*/

void check_io(FILE *file)
{
  if (ferror(file))
501
    die(EX_EOF, "Got errno %d on write", errno);
502 503
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
504 505 506
static void print_version(void)
{
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
monty@mysql.com's avatar
monty@mysql.com committed
507 508
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
  NETWARE_SET_SCREEN_MODE(1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
509 510 511
} /* print_version */


512 513 514 515
static void short_usage_sub(void)
{
  printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
  printf("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
516
         my_progname);
517
  printf("OR     %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
monty@mysql.com's avatar
monty@mysql.com committed
518
  NETWARE_SET_SCREEN_MODE(1);
519 520
}

monty@mysql.com's avatar
monty@mysql.com committed
521

bk@work.mysql.com's avatar
bk@work.mysql.com committed
522 523 524 525 526 527
static void usage(void)
{
  print_version();
  puts("By Igor Romanenko, Monty, Jani & Sinisa");
  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");
  puts("Dumping definition and data mysql database or table");
528
  short_usage_sub();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
529
  print_defaults("my",load_default_groups);
530 531
  my_print_help(my_long_options);
  my_print_variables(my_long_options);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
532 533 534
} /* usage */


535 536 537 538 539 540
static void short_usage(void)
{
  short_usage_sub();
  printf("For more options, use %s --help\n", my_progname);
}

monty@mysql.com's avatar
monty@mysql.com committed
541 542
#include <help_end.h>

543

544
static void write_header(FILE *sql_file, char *db_name)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
545
{
546
  if (opt_xml)
547
  {
548
    fputs("<?xml version=\"1.0\"?>\n", sql_file);
549 550
    /* Schema reference.  Allows use of xsi:nil for NULL values and 
       xsi:type to define an element's data type. */
551 552 553 554
    fputs("<mysqldump ", sql_file);
    fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
          sql_file);
    fputs(">\n", sql_file);
555
    check_io(sql_file);
556
  }
557
  else if (!opt_compact)
558
  {
559 560 561 562
    if (opt_comments)
    {
      fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
      fprintf(sql_file, "-- Host: %s    Database: %s\n",
563 564
              current_host ? current_host : "localhost", db_name ? db_name :
              "");
565
      fputs("-- ------------------------------------------------------\n",
566
            sql_file);
567
      fprintf(sql_file, "-- Server version\t%s\n",
568
              mysql_get_server_info(&mysql_connection));
569
    }
570
    if (opt_set_charset)
bar@bar.intranet.mysql.r18.ru's avatar
bar@bar.intranet.mysql.r18.ru committed
571 572 573 574 575
      fprintf(sql_file,
"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
"\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
"\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
"\n/*!40101 SET NAMES %s */;\n",default_charset);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
576 577 578 579 580 581 582

    if (opt_tz_utc)
    {
      fprintf(sql_file, "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n");
      fprintf(sql_file, "/*!40103 SET TIME_ZONE='+00:00' */;\n");
    }

583 584 585
    if (!path)
    {
      fprintf(md_result_file,"\
586 587 588
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n\
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n\
");
589 590
    }
    fprintf(sql_file,
591 592 593 594
            "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='%s%s%s' */;\n"
            "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n",
            path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",",
            compatible_mode_normal_str);
595
    check_io(sql_file);
596
  }
597
} /* write_header */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
598

599

600 601 602
static void write_footer(FILE *sql_file)
{
  if (opt_xml)
603
  {
604
    fputs("</mysqldump>\n", sql_file);
605 606
    check_io(sql_file);
  }
607
  else if (!opt_compact)
608
  {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
609 610 611
    if (opt_tz_utc)
      fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n");

612 613 614 615
    fprintf(sql_file,"\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n");
    if (!path)
    {
      fprintf(md_result_file,"\
616
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
617
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
618
    }
619
    if (opt_set_charset)
620
      fprintf(sql_file,
bar@bar.intranet.mysql.r18.ru's avatar
bar@bar.intranet.mysql.r18.ru committed
621 622 623
"/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
624
    fprintf(sql_file,
625
            "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
626
    fputs("\n", sql_file);
627 628
    if (opt_comments)
    {
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
629 630 631 632 633 634 635 636 637
      if (opt_dump_date)
      {
        char time_str[20];
        get_date(time_str, GETDATE_DATE_TIME, 0);
        fprintf(sql_file, "-- Dump completed on %s\n",
                time_str);
      }
      else
        fprintf(sql_file, "-- Dump completed");
638
    }
639
    check_io(sql_file);
640
  }
641
} /* write_footer */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
642

monty@mishka.local's avatar
monty@mishka.local committed
643 644 645 646 647 648
static void free_table_ent(char *key)

{
  my_free((gptr) key, MYF(0));
}

649

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
650
byte* get_table_key(const char *entry, uint *length,
651
                                my_bool not_used __attribute__((unused)))
652
{
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
653 654
  *length= strlen(entry);
  return (byte*) entry;
655 656 657
}


658 659
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
660
               char *argument)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
661
{
662
  switch (optid) {
663 664 665 666 667
#ifdef __NETWARE__
  case OPT_AUTO_CLOSE:
    setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
    break;
#endif
668 669 670 671 672 673
  case 'p':
    if (argument)
    {
      char *start=argument;
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
      opt_password=my_strdup(argument,MYF(MY_FAE));
674
      while (*argument) *argument++= 'x';               /* Destroy argument */
675
      if (*start)
676
        start[1]=0;                             /* Cut length of argument */
677
      tty_password= 0;
678 679 680 681 682
    }
    else
      tty_password=1;
    break;
  case 'r':
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
683
    if (!(md_result_file= my_fopen(argument, O_WRONLY | FILE_BINARY,
684
                                    MYF(MY_WME))))
685 686 687
      exit(1);
    break;
  case 'W':
bk@work.mysql.com's avatar
bk@work.mysql.com committed
688
#ifdef __WIN__
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
689
    opt_protocol= MYSQL_PROTOCOL_PIPE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
690
#endif
691
    break;
692 693 694
  case 'N':
    opt_set_charset= 0;
    break;
695 696
  case 'T':
    opt_disable_keys=0;
697 698 699 700 701 702 703 704 705 706 707 708

    if (strlen(argument) >= FN_REFLEN)
    {
      /*
        This check is made because the some the file functions below
        have FN_REFLEN sized stack allocated buffers and will cause
        a crash even if the input destination buffer is large enough
        to hold the output.
      */
      die(EX_USAGE, "Input filename too long: %s", argument);
    }

709 710
    break;
  case '#':
711
    DBUG_PUSH(argument ? argument : default_dbug_option);
712
    info_flag= 1;
713
    break;
714
#include <sslopt-case.h>
715 716
  case 'V': print_version(); exit(0);
  case 'X':
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
717
    opt_xml= 1;
718
    extended_insert= opt_drop= opt_lock=
719
      opt_disable_keys= opt_autocommit= opt_create_db= 0;
720 721 722 723 724
    break;
  case 'I':
  case '?':
    usage();
    exit(0);
725 726 727 728
  case (int) OPT_MASTER_DATA:
    if (!argument) /* work like in old versions */
      opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
    break;
729
  case (int) OPT_OPTIMIZE:
730
    extended_insert= opt_drop= opt_lock= quick= create_options=
731
      opt_disable_keys= lock_tables= opt_set_charset= 1;
732
    break;
733 734
  case (int) OPT_SKIP_OPTIMIZATION:
    extended_insert= opt_drop= opt_lock= quick= create_options=
monty@mishka.local's avatar
monty@mishka.local committed
735
      opt_disable_keys= lock_tables= opt_set_charset= 0;
736
    break;
737 738 739 740
  case (int) OPT_COMPACT:
  if (opt_compact)
  {
    opt_comments= opt_drop= opt_disable_keys= opt_lock= 0;
741
    opt_set_charset= 0;
742
  }
743 744 745
  case (int) OPT_TABLES:
    opt_databases=0;
    break;
746 747
  case (int) OPT_IGNORE_TABLE:
  {
serg@serg.mylan's avatar
serg@serg.mylan committed
748
    if (!strchr(argument, '.'))
749
    {
serg@serg.mylan's avatar
serg@serg.mylan committed
750
      fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n");
751 752
      exit(1);
    }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
753
    if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0))))
serg@serg.mylan's avatar
serg@serg.mylan committed
754
      exit(EX_EOM);
755 756
    break;
  }
757
  case (int) OPT_COMPATIBLE:
serg@serg.mylan's avatar
serg@serg.mylan committed
758
    {
759
      char buff[255];
760 761 762
      char *end= compatible_mode_normal_str;
      int i;
      ulong mode;
763
      uint err_len;
764 765

      opt_quoted= 1;
766
      opt_set_charset= 0;
767 768
      opt_compatible_mode_str= argument;
      opt_compatible_mode= find_set(&compatible_mode_typelib,
769 770
                                    argument, strlen(argument),
                                    &err_ptr, &err_len);
771 772
      if (err_len)
      {
773 774 775
        strmake(buff, err_ptr, min(sizeof(buff), err_len));
        fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
        exit(1);
776
      }
777 778
#if !defined(DBUG_OFF)
      {
779 780 781 782 783 784
        uint size_for_sql_mode= 0;
        const char **ptr;
        for (ptr= compatible_mode_names; *ptr; ptr++)
          size_for_sql_mode+= strlen(*ptr);
        size_for_sql_mode+= sizeof(compatible_mode_names)-1;
        DBUG_ASSERT(sizeof(compatible_mode_normal_str)>=size_for_sql_mode);
785 786 787 788 789
      }
#endif
      mode= opt_compatible_mode;
      for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++)
      {
790 791 792 793 794
        if (mode & 1)
        {
          end= strmov(end, compatible_mode_names[i]);
          end= strmov(end, ",");
        }
795 796
      }
      if (end!=compatible_mode_normal_str)
797 798
        end[-1]= 0;
      /*
799 800 801
        Set charset to the default compiled value if it hasn't
        been reset yet by --default-character-set=xxx.
      */
802
      if (default_charset == mysql_universal_client_charset)
803
        default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
804 805 806
      break;
    }
  case (int) OPT_MYSQL_PROTOCOL:
807
    {
808
      if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0)
809
      {
810 811
        fprintf(stderr, "Unknown option to protocol: %s\n", argument);
        exit(1);
812 813
      }
      break;
814
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
815
  }
816 817 818 819 820 821
  return 0;
}

static int get_options(int *argc, char ***argv)
{
  int ho_error;
822 823 824 825
  MYSQL_PARAMETERS *mysql_params= mysql_get_parameters();

  opt_max_allowed_packet= *mysql_params->p_max_allowed_packet;
  opt_net_buffer_length= *mysql_params->p_net_buffer_length;
826 827 828

  md_result_file= stdout;
  load_defaults("my",load_default_groups,argc,argv);
829
  defaults_argv= *argv;
830

831 832 833 834 835 836 837 838 839 840 841 842 843
  if (hash_init(&ignore_table, charset_info, 16, 0, 0,
                (hash_get_key) get_table_key,
                (hash_free_key) free_table_ent, 0))
    return(EX_EOM);
  /* Don't copy cluster internal log tables */
  if (my_hash_insert(&ignore_table,
                     (byte*) my_strdup("mysql.apply_status", MYF(MY_WME))) ||
      my_hash_insert(&ignore_table,
                     (byte*) my_strdup("mysql.schema", MYF(MY_WME))))
    return(EX_EOM);

  if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
    return(ho_error);
844

845 846 847
  *mysql_params->p_max_allowed_packet= opt_max_allowed_packet;
  *mysql_params->p_net_buffer_length= opt_net_buffer_length;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
848
  if (opt_delayed)
849
    opt_lock=0;                         /* Can't have lock with delayed */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
850
  if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
851
                fields_terminated))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
852
  {
853
    fprintf(stderr,
854
            "%s: You must use option --tab with --fields-...\n", my_progname);
855
    return(EX_USAGE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
856
  }
857 858 859 860 861 862 863 864

  /* Ensure consistency of the set of binlog & locking options */
  if (opt_delete_master_logs && !opt_master_data)
    opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL;
  if (opt_single_transaction && opt_lock_all_tables)
  {
    fprintf(stderr, "%s: You can't use --single-transaction and "
            "--lock-all-tables at the same time.\n", my_progname);
865
    return(EX_USAGE);
866
  }
867 868 869
  if (opt_master_data)
    opt_lock_all_tables= !opt_single_transaction;
  if (opt_single_transaction || opt_lock_all_tables)
870
    lock_tables= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
871 872 873
  if (enclosed && opt_enclosed)
  {
    fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
874
    return(EX_USAGE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
875 876 877 878
  }
  if ((opt_databases || opt_alldbs) && path)
  {
    fprintf(stderr,
879 880
            "%s: --databases or --all-databases can't be used with --tab.\n",
            my_progname);
881
    return(EX_USAGE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
882
  }
883
  if (strcmp(default_charset, charset_info->csname) &&
884 885
      !(charset_info= get_charset_by_csname(default_charset,
                                            MY_CS_PRIMARY, MYF(MY_WME))))
886
    exit(1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
887 888
  if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
  {
889
    short_usage();
890
    return EX_USAGE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
891 892
  }
  if (tty_password)
893
    opt_password=get_tty_password(NullS);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
894 895 896 897 898
  return(0);
} /* get_options */


/*
899
** DB_error -- prints mysql error message and exits the program.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
900
*/
901
static void DB_error(MYSQL *mysql_arg, const char *when)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
902
{
903
  DBUG_ENTER("DB_error");
904
  maybe_die(EX_MYSQLERR, "Got error: %d: %s %s",
905
          mysql_errno(mysql_arg), mysql_error(mysql_arg), when);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
906
  DBUG_VOID_RETURN;
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
}



/*
  Prints out an error message and kills the process.

  SYNOPSIS
    die()
    error_num   - process return value
    fmt_reason  - a format string for use by my_vsnprintf.
    ...         - variable arguments for above fmt_reason string
  
  DESCRIPTION
    This call prints out the formatted error message to stderr and then
    terminates the process.
*/
static void die(int error_num, const char* fmt_reason, ...)
{
  char buffer[1000];
  va_list args;
  va_start(args,fmt_reason);
  my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
  va_end(args);

  fprintf(stderr, "%s: %s\n", my_progname, buffer);
  fflush(stderr);

  ignore_errors= 0; /* force the exit */
  maybe_exit(error_num);
}


/*
  Prints out an error message and maybe kills the process.

  SYNOPSIS
    maybe_die()
    error_num   - process return value
    fmt_reason  - a format string for use by my_vsnprintf.
    ...         - variable arguments for above fmt_reason string
  
  DESCRIPTION
    This call prints out the formatted error message to stderr and then
    terminates the process, unless the --force command line option is used.
    
    This call should be used for non-fatal errors (such as database
    errors) that the code may still be able to continue to the next unit
    of work.
    
*/
static void maybe_die(int error_num, const char* fmt_reason, ...)
{
  char buffer[1000];
  va_list args;
  va_start(args,fmt_reason);
  my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
  va_end(args);

  fprintf(stderr, "%s: %s\n", my_progname, buffer);
  fflush(stderr);

  maybe_exit(error_num);
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
972 973


974 975 976 977 978 979 980
/*
  Sends a query to server, optionally reads result, prints error message if
  some.

  SYNOPSIS
    mysql_query_with_error_report()
    mysql_con       connection to use
monty@mysql.com's avatar
monty@mysql.com committed
981
    res             if non zero, result will be put there with
982
                    mysql_store_result()
983 984 985 986 987 988
    query           query to send to server

  RETURN VALUES
    0               query sending and (if res!=0) result reading went ok
    1               error
*/
989

990 991 992 993 994 995
static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res,
                                         const char *query)
{
  if (mysql_query(mysql_con, query) ||
      (res && !((*res)= mysql_store_result(mysql_con))))
  {
996 997
    maybe_die(EX_MYSQLERR, "Couldn't execute '%s': %s (%d)",
            query, mysql_error(mysql_con), mysql_errno(mysql_con));
998 999 1000 1001 1002
    return 1;
  }
  return 0;
}

1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017

static int switch_character_set_results(MYSQL *mysql, const char *cs_name)
{
  char query_buffer[QUERY_LENGTH];
  size_t query_length;

  query_length= my_snprintf(query_buffer,
                            sizeof (query_buffer),
                            "SET SESSION character_set_results = '%s'",
                            (const char *) cs_name);

  return mysql_real_query(mysql, query_buffer, query_length);
}


1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
/*
  Open a new .sql file to dump the table or view into

  SYNOPSIS
    open_sql_file_for_table
    name      name of the table or view

  RETURN VALUES
    0        Failed to open file
    > 0      Handle of the open file
*/
static FILE* open_sql_file_for_table(const char* table)
{
  FILE* res;
  char filename[FN_REFLEN], tmp_path[FN_REFLEN];
  convert_dirname(tmp_path,path,NullS);
  res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
1035
                O_WRONLY, MYF(MY_WME));
1036 1037 1038
  return res;
}

1039

1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
static void free_resources()
{
  if (md_result_file && md_result_file != stdout)
    my_fclose(md_result_file, MYF(0));
  my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
  if (hash_inited(&ignore_table))
    hash_free(&ignore_table);
  if (extended_insert)
    dynstr_free(&extended_row);
  if (insert_pat_inited)
    dynstr_free(&insert_pat);
  if (defaults_argv)
    free_defaults(defaults_argv);
  my_end(info_flag ? MY_CHECK_ERROR : 0);
}


1057
static void maybe_exit(int error)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1058 1059 1060 1061 1062
{
  if (!first_error)
    first_error= error;
  if (ignore_errors)
    return;
1063 1064
  if (mysql)
    mysql_close(mysql);
1065
  free_resources();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1066 1067 1068 1069 1070
  exit(error);
}


/*
1071
  db_connect -- connects to the host and selects DB.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1072
*/
1073 1074

static int connect_to_db(char *host, char *user,char *passwd)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1075
{
1076
  char buff[20+FN_REFLEN];
1077
  DBUG_ENTER("connect_to_db");
1078 1079

  verbose_msg("-- Connecting to %s...\n", host ? host : "localhost");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1080 1081 1082 1083 1084 1085
  mysql_init(&mysql_connection);
  if (opt_compress)
    mysql_options(&mysql_connection,MYSQL_OPT_COMPRESS,NullS);
#ifdef HAVE_OPENSSL
  if (opt_use_ssl)
    mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
1086
                  opt_ssl_capath, opt_ssl_cipher);
1087 1088
  mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
                (char*)&opt_ssl_verify_server_cert);
1089 1090 1091 1092 1093 1094
#endif
  if (opt_protocol)
    mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
#ifdef HAVE_SMEM
  if (shared_memory_base_name)
    mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1095
#endif
1096
  mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
1097
  if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd,
1098 1099
                                  NULL,opt_mysql_port,opt_mysql_unix_port,
                                  0)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1100
  {
1101
    DB_error(&mysql_connection, "when trying to connect");
1102
    DBUG_RETURN(1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1103
  }
bar@mysql.com's avatar
bar@mysql.com committed
1104 1105 1106 1107 1108
  /*
    Don't dump SET NAMES with a pre-4.1 server (bug#7997).
  */
  if (mysql_get_server_version(&mysql_connection) < 40100)
    opt_set_charset= 0;
1109 1110 1111 1112
  /*
    As we're going to set SQL_MODE, it would be lost on reconnect, so we
    cannot reconnect.
  */
1113
  mysql->reconnect= 0;
1114
  my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */",
1115
              compatible_mode_normal_str);
1116
  if (mysql_query_with_error_report(mysql, 0, buff))
1117
    DBUG_RETURN(1);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1118
  /*
1119
    set time_zone to UTC to allow dumping date types between servers with
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1120 1121 1122 1123 1124
    different time zone settings
  */
  if (opt_tz_utc)
  {
    my_snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */");
1125
    if (mysql_query_with_error_report(mysql, 0, buff))
1126
      DBUG_RETURN(1);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1127
  }
1128 1129
  DBUG_RETURN(0);
} /* connect_to_db */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1130 1131 1132 1133 1134 1135 1136


/*
** dbDisconnect -- disconnects from the host.
*/
static void dbDisconnect(char *host)
{
1137
  verbose_msg("-- Disconnecting from %s...\n", host ? host : "localhost");
1138
  mysql_close(mysql);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1139 1140 1141 1142 1143 1144 1145 1146
} /* dbDisconnect */


static void unescape(FILE *file,char *pos,uint length)
{
  char *tmp;
  DBUG_ENTER("unescape");
  if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
1147 1148
    die(EX_MYSQLERR, "Couldn't allocate memory");

1149
  mysql_real_escape_string(&mysql_connection, tmp, pos, length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1150 1151 1152
  fputc('\'', file);
  fputs(tmp, file);
  fputc('\'', file);
1153
  check_io(file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1154 1155 1156 1157 1158 1159 1160 1161 1162
  my_free(tmp, MYF(MY_WME));
  DBUG_VOID_RETURN;
} /* unescape */


static my_bool test_if_special_chars(const char *str)
{
#if MYSQL_VERSION_ID >= 32300
  for ( ; *str ; str++)
1163
    if (!my_isvar(charset_info,*str) && *str != '$')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1164 1165 1166 1167 1168
      return 1;
#endif
  return 0;
} /* test_if_special_chars */

1169

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1170

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1171 1172 1173
/*
  quote_name(name, buff, force)

1174
  Quotes char string, taking into account compatible mode
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1175 1176 1177 1178 1179

  Args

  name                 Unquoted string containing that which will be quoted
  buff                 The buffer that contains the quoted value, also returned
1180
  force                Flag to make it ignore 'test_if_special_chars'
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1181 1182 1183 1184 1185 1186

  Returns

  buff                 quoted string

*/
1187
static char *quote_name(const char *name, char *buff, my_bool force)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1188
{
1189
  char *to= buff;
1190 1191
  char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';

1192 1193
  if (!force && !opt_quoted && !test_if_special_chars(name))
    return (char*) name;
1194
  *to++= qtype;
1195 1196
  while (*name)
  {
1197 1198
    if (*name == qtype)
      *to++= qtype;
1199 1200
    *to++= *name++;
  }
1201 1202
  to[0]= qtype;
  to[1]= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1203 1204 1205
  return buff;
} /* quote_name */

monty@mishka.local's avatar
monty@mishka.local committed
1206

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1207 1208
/*
  Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1209

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1210
  SYNOPSIS
monty@mishka.local's avatar
monty@mishka.local committed
1211 1212 1213
    quote_for_like()
    name     name of the table
    buff     quoted name of the table
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1214 1215 1216

  DESCRIPTION
    Quote \, _, ' and % characters
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1217

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228
    Note: Because MySQL uses the C escape syntax in strings
    (for example, '\n' to represent newline), you must double
    any '\' that you use in your LIKE  strings. For example, to
    search for '\n', specify it as '\\n'. To search for '\', specify
    it as '\\\\' (the backslashes are stripped once by the parser
    and another time when the pattern match is done, leaving a
    single backslash to be matched).

    Example: "t\1" => "t\\\\1"

*/
1229 1230 1231 1232 1233 1234
static char *quote_for_like(const char *name, char *buff)
{
  char *to= buff;
  *to++= '\'';
  while (*name)
  {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1235 1236 1237 1238 1239 1240 1241
    if (*name == '\\')
    {
      *to++='\\';
      *to++='\\';
      *to++='\\';
    }
    else if (*name == '\'' || *name == '_'  || *name == '%')
1242 1243 1244 1245 1246 1247 1248 1249 1250
      *to++= '\\';
    *to++= *name++;
  }
  to[0]= '\'';
  to[1]= 0;
  return buff;
}


1251 1252
/*
  Quote and print a string.
1253

1254 1255
  SYNOPSIS
    print_quoted_xml()
1256
    xml_file    - output file
1257 1258 1259
    str         - string to print
    len         - its length

1260
  DESCRIPTION
1261
    Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1262 1263 1264 1265 1266
*/

static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
{
  const char *end;
1267

1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
  for (end= str + len; str != end; str++)
  {
    switch (*str) {
    case '<':
      fputs("&lt;", xml_file);
      break;
    case '>':
      fputs("&gt;", xml_file);
      break;
    case '&':
      fputs("&amp;", xml_file);
      break;
    case '\"':
      fputs("&quot;", xml_file);
      break;
    default:
      fputc(*str, xml_file);
      break;
    }
  }
1288
  check_io(xml_file);
1289 1290 1291 1292
}


/*
1293
  Print xml tag. Optionally add attribute(s).
1294

1295
  SYNOPSIS
1296 1297 1298 1299
    print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name, 
                    ..., attribute_name_n, attribute_value_n, NullS)
    xml_file              - output file
    sbeg                  - line beginning
1300
    line_end              - line ending
1301 1302 1303 1304 1305
    tag_name              - XML tag name.
    first_attribute_name  - tag and first attribute
    first_attribute_value - (Implied) value of first attribute
    attribute_name_n      - attribute n
    attribute_value_n     - value of attribute n
1306

1307
  DESCRIPTION
1308 1309 1310 1311 1312
    Print XML tag with any number of attribute="value" pairs to the xml_file.

    Format is:
      sbeg<tag_name first_attribute_name="first_attribute_value" ... 
      attribute_name_n="attribute_value_n">send
1313
  NOTE
1314 1315 1316 1317
    Additional arguments must be present in attribute/value pairs.
    The last argument should be the null character pointer.
    All attribute_value arguments MUST be NULL terminated strings.
    All attribute_value arguments will be quoted before output.
1318 1319
*/

1320 1321
static void print_xml_tag(FILE * xml_file, const char* sbeg,
                          const char* line_end, 
1322 1323
                          const char* tag_name, 
                          const char* first_attribute_name, ...)
1324
{
1325
  va_list arg_list;
1326
  const char *attribute_name, *attribute_value;
1327

1328
  fputs(sbeg, xml_file);
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
  fputc('<', xml_file);
  fputs(tag_name, xml_file);  

  va_start(arg_list, first_attribute_name);
  attribute_name= first_attribute_name;
  while (attribute_name != NullS)
  {
    attribute_value= va_arg(arg_list, char *);
    DBUG_ASSERT(attribute_value != NullS);

    fputc(' ', xml_file);
    fputs(attribute_name, xml_file);    
    fputc('\"', xml_file);
    
    print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
    fputc('\"', xml_file);

    attribute_name= va_arg(arg_list, char *);
  }
  va_end(arg_list);

  fputc('>', xml_file);
1351
  fputs(line_end, xml_file);
1352
  check_io(xml_file);
1353 1354 1355
}


1356 1357 1358 1359 1360
/*
  Print xml tag with for a field that is null

  SYNOPSIS
    print_xml_null_tag()
1361 1362 1363 1364
    xml_file    - output file
    sbeg        - line beginning
    stag_atr    - tag and attribute
    sval        - value of attribute
1365
    line_end        - line ending
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376

  DESCRIPTION
    Print tag with one attribute to the xml_file. Format is:
      <stag_atr="sval" xsi:nil="true"/>
  NOTE
    sval MUST be a NULL terminated string.
    sval string will be qouted before output.
*/

static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
                               const char* stag_atr, const char* sval,
1377
                               const char* line_end)
1378 1379 1380 1381 1382 1383 1384
{
  fputs(sbeg, xml_file);
  fputs("<", xml_file);
  fputs(stag_atr, xml_file);
  fputs("\"", xml_file);
  print_quoted_xml(xml_file, sval, strlen(sval));
  fputs("\" xsi:nil=\"true\" />", xml_file);
1385
  fputs(line_end, xml_file);
1386 1387 1388 1389
  check_io(xml_file);
}


1390 1391 1392 1393 1394
/*
  Print xml tag with many attributes.

  SYNOPSIS
    print_xml_row()
1395 1396 1397 1398 1399
    xml_file    - output file
    row_name    - xml tag name
    tableRes    - query result
    row         - result row

1400 1401 1402 1403 1404 1405 1406 1407
  DESCRIPTION
    Print tag with many attribute to the xml_file. Format is:
      \t\t<row_name Atr1="Val1" Atr2="Val2"... />
  NOTE
    All atributes and values will be quoted before output.
*/

static void print_xml_row(FILE *xml_file, const char *row_name,
1408
                          MYSQL_RES *tableRes, MYSQL_ROW *row)
1409 1410 1411 1412
{
  uint i;
  MYSQL_FIELD *field;
  ulong *lengths= mysql_fetch_lengths(tableRes);
1413

1414
  fprintf(xml_file, "\t\t<%s", row_name);
1415
  check_io(xml_file);
1416 1417 1418
  mysql_field_seek(tableRes, 0);
  for (i= 0; (field= mysql_fetch_field(tableRes)); i++)
  {
1419
    if ((*row)[i])
1420
    {
monty@mishka.local's avatar
monty@mishka.local committed
1421
      fputc(' ', xml_file);
1422
      print_quoted_xml(xml_file, field->name, field->name_length);
1423 1424
      fputs("=\"", xml_file);
      print_quoted_xml(xml_file, (*row)[i], lengths[i]);
monty@mishka.local's avatar
monty@mishka.local committed
1425
      fputc('"', xml_file);
1426
      check_io(xml_file);
1427 1428 1429
    }
  }
  fputs(" />\n", xml_file);
1430
  check_io(xml_file);
1431 1432
}

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
/*
  Print hex value for blob data.

  SYNOPSIS
    print_blob_as_hex()
    output_file         - output file
    str                 - string to print
    len                 - its length

  DESCRIPTION
    Print hex value for blob data.
*/

static void print_blob_as_hex(FILE *output_file, const char *str, ulong len)
{
    /* sakaik got the idea to to provide blob's in hex notation. */
1449
    const char *ptr= str, *end= ptr + len;
1450 1451 1452 1453 1454
    for (; ptr < end ; ptr++)
      fprintf(output_file, "%02X", *((uchar *)ptr));
    check_io(output_file);
}

1455 1456
/*
  dump_routines_for_db
1457
  -- retrieves list of routines for a given db, and prints out
1458 1459 1460 1461 1462
  the CREATE PROCEDURE definition into the output (the dump).

  This function has logic to print the appropriate syntax depending on whether
  this is a procedure or functions

1463 1464 1465
  RETURN
    0  Success
    1  Error
1466 1467
*/

1468
static uint dump_routines_for_db(char *db)
1469
{
1470
  char       query_buff[512];
1471 1472 1473
  const char *routine_type[]= {"FUNCTION", "PROCEDURE"};
  char       db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
  char       *routine_name;
1474
  int        i;
1475
  FILE       *sql_file= md_result_file;
1476
  MYSQL_RES  *routine_res, *routine_list_res;
1477
  MYSQL_ROW  row, routine_list_row;
1478
  DBUG_ENTER("dump_routines_for_db");
1479
  DBUG_PRINT("enter", ("db: '%s'", db));
1480

1481
  mysql_real_escape_string(mysql, db_name_buff, db, strlen(db));
1482 1483 1484 1485

  /* nice comments */
  if (opt_comments)
    fprintf(sql_file, "\n--\n-- Dumping routines for database '%s'\n--\n", db);
1486 1487

  /*
1488 1489
    not using "mysql_query_with_error_report" because we may have not
    enough privileges to lock mysql.proc.
1490
  */
1491
  if (lock_tables)
1492
    mysql_query(mysql, "LOCK TABLES mysql.proc READ");
1493

1494 1495 1496
  if (opt_compact)
    fprintf(sql_file, "\n/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n");

1497
  fprintf(sql_file, "DELIMITER ;;\n");
1498 1499

  /* 0, retrieve and dump functions, 1, procedures */
1500
  for (i= 0; i <= 1; i++)
1501 1502 1503
  {
    my_snprintf(query_buff, sizeof(query_buff),
                "SHOW %s STATUS WHERE Db = '%s'",
1504
                routine_type[i], db_name_buff);
1505

1506
    if (mysql_query_with_error_report(mysql, &routine_list_res, query_buff))
1507 1508 1509 1510 1511
      DBUG_RETURN(1);

    if (mysql_num_rows(routine_list_res))
    {

1512
      while ((routine_list_row= mysql_fetch_row(routine_list_res)))
1513
      {
1514 1515
        DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i],
                            name_buff));
1516
        routine_name= quote_name(routine_list_row[1], name_buff, 0);
1517
        my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s",
1518
                    routine_type[i], routine_name);
1519

1520
        if (mysql_query_with_error_report(mysql, &routine_res, query_buff))
1521 1522
          DBUG_RETURN(1);

1523
        while ((row= mysql_fetch_row(routine_res)))
1524 1525
        {
          /*
1526 1527
            if the user has EXECUTE privilege he see routine names, but NOT the
            routine body of other routines that are not the creator of!
1528 1529
          */
          DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d",
1530 1531 1532 1533 1534 1535 1536 1537 1538
                             routine_name, row[2] ? row[2] : "(null)",
                             row[2] ? (int) strlen(row[2]) : 0));
          if (row[2] == NULL)
          {
            fprintf(sql_file, "\n-- insufficient privileges to %s\n", query_buff);
            fprintf(sql_file, "-- does %s have permissions on mysql.proc?\n\n", current_user);
            maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff);
          }
          else if (strlen(row[2]))
1539
          {
1540 1541 1542
            char *query_str= NULL;
            char *definer_begin;

1543
            if (opt_drop)
1544
              fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n",
1545
                      routine_type[i], routine_name);
1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556

            /*
              Cover DEFINER-clause in version-specific comments.

              TODO: this is definitely a BAD IDEA to parse SHOW CREATE output.
              We should user INFORMATION_SCHEMA instead. The only problem is
              that now INFORMATION_SCHEMA does not provide information about
              routine parameters.
            */

            definer_begin= strstr(row[2], " DEFINER");
1557

1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
            if (definer_begin)
            {
              char *definer_end= strstr(definer_begin, " PROCEDURE");

              if (!definer_end)
                definer_end= strstr(definer_begin, " FUNCTION");

              if (definer_end)
              {
                char *query_str_tail;

                /*
                  Allocate memory for new query string: original string
                  from SHOW statement and version-specific comments.
                */
                query_str= alloc_query_str(strlen(row[2]) + 23);

                query_str_tail= strnmov(query_str, row[2],
                                        definer_begin - row[2]);
1577
                query_str_tail= strmov(query_str_tail, "*/ /*!50020");
1578 1579 1580 1581 1582 1583 1584
                query_str_tail= strnmov(query_str_tail, definer_begin,
                                        definer_end - definer_begin);
                query_str_tail= strxmov(query_str_tail, "*/ /*!50003",
                                        definer_end, NullS);
              }
            }

1585
            /*
1586 1587
              we need to change sql_mode only for the CREATE
              PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name
1588
            */
1589
            fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n",
1590
                    row[1] /* sql_mode */);
1591 1592
            fprintf(sql_file, "/*!50003 %s */;;\n",
                    (query_str != NULL ? query_str : row[2]));
1593 1594 1595
            fprintf(sql_file,
                    "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/"
                    ";;\n");
1596 1597

            my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
1598 1599
          }
        } /* end of routine printing */
dkatz/Damien@damiendev's avatar
dkatz/Damien@damiendev committed
1600 1601
        mysql_free_result(routine_res);

1602 1603 1604 1605
      } /* end of list of routines */
    }
    mysql_free_result(routine_list_res);
  } /* end of for i (0 .. 1)  */
1606 1607
  /* set the delimiter back to ';' */
  fprintf(sql_file, "DELIMITER ;\n");
1608

1609
  if (lock_tables)
1610
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
1611 1612
  DBUG_RETURN(0);
}
1613

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1614
/*
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1615 1616 1617 1618 1619 1620 1621
  get_table_structure -- retrievs database structure, prints out corresponding
  CREATE statement and fills out insert_pat if the table is the type we will
  be dumping.

  ARGS
    table       - table name
    db          - db name
1622
    table_type  - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1623
    ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1624 1625 1626

  RETURN
    number of fields in table, 0 if error
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1627
*/
1628

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1629 1630
static uint get_table_structure(char *table, char *db, char *table_type,
                                char *ignore_flag)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1631
{
monty@mysql.com's avatar
monty@mysql.com committed
1632
  my_bool    init=0, delayed, write_data, complete_insert;
1633
  my_ulonglong num_fields;
1634
  char       *result_table, *opt_quoted_table;
1635
  const char *insert_option;
1636 1637
  char       name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
  char       table_buff2[NAME_LEN*2+3], query_buff[512];
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
1638
  FILE       *sql_file= md_result_file;
1639
  int        len;
1640 1641 1642
  MYSQL_RES  *result;
  MYSQL_ROW  row;

1643
  DBUG_ENTER("get_table_structure");
monty@mysql.com's avatar
monty@mysql.com committed
1644
  DBUG_PRINT("enter", ("db: %s  table: %s", db, table));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1645

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1646 1647
  *ignore_flag= check_if_ignore_table(table, table_type);

monty@mysql.com's avatar
monty@mysql.com committed
1648 1649 1650 1651
  delayed= opt_delayed;
  if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
  {
    delayed= 0;
1652 1653
    verbose_msg("-- Warning: Unable to use delayed inserts for table '%s' "
                "because it's of type %s\n", table, table_type);
monty@mysql.com's avatar
monty@mysql.com committed
1654
  }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1655

monty@mysql.com's avatar
monty@mysql.com committed
1656 1657
  complete_insert= 0;
  if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1658
  {
monty@mysql.com's avatar
monty@mysql.com committed
1659
    complete_insert= opt_complete_insert;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1660
    if (!insert_pat_inited)
1661 1662
    {
      insert_pat_inited= 1;
1663
      init_dynamic_string_checked(&insert_pat, "", 1024, 1024);
1664
    }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1665
    else
1666
      dynstr_set_checked(&insert_pat, "");
1667 1668
  }

monty@mysql.com's avatar
monty@mysql.com committed
1669 1670
  insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
                  delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1671

1672
  verbose_msg("-- Retrieving table structure for table %s...\n", table);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1673

1674 1675 1676
  len= my_snprintf(query_buff, sizeof(query_buff),
                   "SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
                   (opt_quoted || opt_keywords));
monty@mishka.local's avatar
monty@mishka.local committed
1677
  if (!create_options)
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1678 1679
    strmov(query_buff+len,
           "/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */");
monty@mishka.local's avatar
monty@mishka.local committed
1680

1681 1682
  result_table=     quote_name(table, table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);
1683 1684

  if (opt_order_by_primary)
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
1685
    order_by= primary_key_fields(result_table);
1686

1687
  if (!opt_xml && !mysql_query_with_error_report(mysql, 0, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1688
  {
1689
    /* using SHOW CREATE statement */
1690
    if (!opt_no_create_info)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1691
    {
1692 1693
      /* Make an sql-file, if path was given iow. option -T was given */
      char buff[20+FN_REFLEN];
1694
      MYSQL_FIELD *field;
1695

1696
      my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
1697 1698 1699 1700

      if (switch_character_set_results(mysql, "binary") ||
          mysql_query_with_error_report(mysql, &result, buff) ||
          switch_character_set_results(mysql, default_charset))
1701
        DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1702

1703 1704
      if (path)
      {
1705
        if (!(sql_file= open_sql_file_for_table(table)))
1706
          DBUG_RETURN(0);
1707

1708
        write_header(sql_file, db);
1709
      }
1710
      if (!opt_xml && opt_comments)
1711
      {
1712 1713 1714 1715
      if (strcmp (table_type, "VIEW") == 0)         /* view */
        fprintf(sql_file, "\n--\n-- Temporary table structure for view %s\n--\n\n",
                result_table);
      else
monty@mysql.com's avatar
monty@mysql.com committed
1716
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1717 1718
                result_table);
        check_io(sql_file);
1719
      }
1720
      if (opt_drop)
1721
      {
1722 1723 1724 1725 1726 1727 1728
      /*
        Even if the "table" is a view, we do a DROP TABLE here.  The
        view-specific code below fills in the DROP VIEW.
       */
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
                opt_quoted_table);
        check_io(sql_file);
1729
      }
1730

1731
      field= mysql_fetch_field_direct(result, 0);
1732 1733
      if (strcmp(field->name, "View") == 0)
      {
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
1734
        char *scv_buff= NULL;
1735

1736
        verbose_msg("-- It's a view, create dummy table for view\n");
1737

1738 1739 1740 1741
        /* save "show create" statement for later */
        if ((row= mysql_fetch_row(result)) && (scv_buff=row[1]))
          scv_buff= my_strdup(scv_buff, MYF(0));

1742 1743 1744
        mysql_free_result(result);

        /*
1745
          Create a table with the same name as the view and with columns of
1746 1747
          the same name in order to satisfy views that depend on this view.
          The table will be removed when the actual view is created.
1748

1749 1750
          The properties of each column, aside from the data type, are not
          preserved in this temporary table, because they are not necessary.
1751

1752 1753 1754
          This will not be necessary once we can determine dependencies
          between views and can simply dump them in the appropriate order.
        */
1755
        my_snprintf(query_buff, sizeof(query_buff),
1756
                    "SHOW FIELDS FROM %s", result_table);
1757
        if (mysql_query_with_error_report(mysql, 0, query_buff))
1758
        {
1759 1760 1761 1762 1763 1764
          /*
            View references invalid or privileged table/col/fun (err 1356),
            so we cannot create a stand-in table.  Be defensive and dump
            a comment with the view's 'show create' statement. (Bug #17371)
          */

1765
          if (mysql_errno(mysql) == ER_VIEW_INVALID)
1766 1767 1768 1769
            fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : "");

          my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));

grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
1770
          DBUG_RETURN(0);
1771
        }
1772 1773
        else
          my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
1774

1775
        if ((result= mysql_store_result(mysql)))
1776
        {
1777 1778 1779 1780
          if (mysql_num_rows(result))
          {
            if (opt_drop)
            {
1781 1782 1783 1784 1785
            /*
              We have already dropped any table of the same name
              above, so here we just drop the view.
             */

1786 1787 1788 1789
              fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
                      opt_quoted_table);
              check_io(sql_file);
            }
1790

1791 1792 1793 1794 1795 1796 1797 1798
            fprintf(sql_file, "/*!50001 CREATE TABLE %s (\n", result_table);
            /*
               Get first row, following loop will prepend comma - keeps
               from having to know if the row being printed is last to
               determine if there should be a _trailing_ comma.
            */
            row= mysql_fetch_row(result);

1799 1800
            fprintf(sql_file, "  %s %s", quote_name(row[0], name_buff, 0),
                    row[1]);
1801 1802 1803 1804 1805 1806 1807 1808 1809 1810

            while((row= mysql_fetch_row(result)))
            {
              /* col name, col type */
              fprintf(sql_file, ",\n  %s %s",
                      quote_name(row[0], name_buff, 0), row[1]);
            }
            fprintf(sql_file, "\n) */;\n");
            check_io(sql_file);
          }
1811
        }
1812 1813
        mysql_free_result(result);

1814 1815 1816
        if (path)
          my_fclose(sql_file, MYF(MY_WME));

1817
        seen_views= 1;
1818 1819
        DBUG_RETURN(0);
      }
1820 1821

      row= mysql_fetch_row(result);
1822 1823 1824 1825 1826 1827 1828 1829

      fprintf(sql_file,
              "SET @saved_cs_client     = @@character_set_client;\n"
              "SET character_set_client = utf8;\n"
              "%s;\n"
              "SET character_set_client = @saved_cs_client;\n",
              row[1]);

1830
      check_io(sql_file);
1831
      mysql_free_result(result);
1832
    }
1833
    my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1834
                result_table);
1835
    if (mysql_query_with_error_report(mysql, &result, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1836
    {
1837
      if (path)
1838
        my_fclose(sql_file, MYF(MY_WME));
1839
      DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1840
    }
1841

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1842
    /*
monty@mysql.com's avatar
monty@mysql.com committed
1843 1844 1845 1846
      If write_data is true, then we build up insert statements for
      the table's data. Note: in subsequent lines of code, this test
      will have to be performed each time we are appending to
      insert_pat.
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1847
    */
monty@mysql.com's avatar
monty@mysql.com committed
1848
    if (write_data)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1849
    {
1850 1851 1852 1853
      dynstr_append_checked(&insert_pat, "INSERT ");
      dynstr_append_checked(&insert_pat, insert_option);
      dynstr_append_checked(&insert_pat, "INTO ");
      dynstr_append_checked(&insert_pat, opt_quoted_table);
monty@mysql.com's avatar
monty@mysql.com committed
1854
      if (complete_insert)
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1855
      {
1856
        dynstr_append_checked(&insert_pat, " (");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1857 1858 1859
      }
      else
      {
1860
        dynstr_append_checked(&insert_pat, " VALUES ");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1861
        if (!extended_insert)
1862
          dynstr_append_checked(&insert_pat, "(");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1863
      }
1864 1865
    }

1866
    while ((row= mysql_fetch_row(result)))
1867
    {
monty@mysql.com's avatar
monty@mysql.com committed
1868
      if (complete_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1869
      {
monty@mysql.com's avatar
monty@mysql.com committed
1870 1871
        if (init)
        {
1872
          dynstr_append_checked(&insert_pat, ", ");
monty@mysql.com's avatar
monty@mysql.com committed
1873 1874
        }
        init=1;
1875
        dynstr_append_checked(&insert_pat,
1876
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
monty@mysql.com's avatar
monty@mysql.com committed
1877
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1878
    }
1879 1880
    num_fields= mysql_num_rows(result);
    mysql_free_result(result);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1881
  }
1882
  else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1883
  {
1884
    verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
1885
                my_progname, mysql_error(mysql));
1886

1887
    my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1888
                result_table);
1889
    if (mysql_query_with_error_report(mysql, &result, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1890 1891
      DBUG_RETURN(0);

1892
    /* Make an sql-file, if path was given iow. option -T was given */
1893
    if (!opt_no_create_info)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1894
    {
1895
      if (path)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1896
      {
1897
        if (!(sql_file= open_sql_file_for_table(table)))
1898
          DBUG_RETURN(0);
1899
        write_header(sql_file, db);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1900
      }
1901
      if (!opt_xml && opt_comments)
1902 1903
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
                result_table);
1904
      if (opt_drop)
monty@mishka.local's avatar
monty@mishka.local committed
1905
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1906
      if (!opt_xml)
1907
        fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
1908
      else
1909 1910
        print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table, 
                NullS);
1911
      check_io(sql_file);
1912
    }
1913

monty@mysql.com's avatar
monty@mysql.com committed
1914
    if (write_data)
1915
    {
1916 1917 1918 1919
      dynstr_append_checked(&insert_pat, "INSERT ");
      dynstr_append_checked(&insert_pat, insert_option);
      dynstr_append_checked(&insert_pat, "INTO ");
      dynstr_append_checked(&insert_pat, result_table);
1920
      if (complete_insert)
1921
        dynstr_append_checked(&insert_pat, " (");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1922 1923
      else
      {
1924
        dynstr_append_checked(&insert_pat, " VALUES ");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1925
        if (!extended_insert)
1926
          dynstr_append_checked(&insert_pat, "(");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1927
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1928
    }
1929

1930
    while ((row= mysql_fetch_row(result)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1931
    {
1932
      ulong *lengths= mysql_fetch_lengths(result);
1933
      if (init)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1934
      {
1935
        if (!opt_xml && !opt_no_create_info)
1936 1937 1938 1939
        {
          fputs(",\n",sql_file);
          check_io(sql_file);
        }
monty@mysql.com's avatar
monty@mysql.com committed
1940
        if (complete_insert)
1941
          dynstr_append_checked(&insert_pat, ", ");
1942 1943
      }
      init=1;
1944
      if (complete_insert)
1945
        dynstr_append_checked(&insert_pat,
1946
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1947
      if (!opt_no_create_info)
1948
      {
1949 1950 1951 1952 1953
        if (opt_xml)
        {
          print_xml_row(sql_file, "field", result, &row);
          continue;
        }
1954

1955
        if (opt_keywords)
1956 1957 1958
          fprintf(sql_file, "  %s.%s %s", result_table,
                  quote_name(row[SHOW_FIELDNAME],name_buff, 0),
                  row[SHOW_TYPE]);
1959
        else
1960 1961 1962
          fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
                                                  name_buff, 0),
                  row[SHOW_TYPE]);
1963 1964
        if (row[SHOW_DEFAULT])
        {
1965 1966
          fputs(" DEFAULT ", sql_file);
          unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1967 1968
        }
        if (!row[SHOW_NULL][0])
1969
          fputs(" NOT NULL", sql_file);
1970
        if (row[SHOW_EXTRA][0])
1971 1972
          fprintf(sql_file, " %s",row[SHOW_EXTRA]);
        check_io(sql_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1973 1974
      }
    }
1975 1976
    num_fields= mysql_num_rows(result);
    mysql_free_result(result);
1977
    if (!opt_no_create_info)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1978
    {
1979 1980 1981
      /* Make an sql-file, if path was given iow. option -T was given */
      char buff[20+FN_REFLEN];
      uint keynr,primary_key;
1982
      my_snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1983
      if (mysql_query_with_error_report(mysql, &result, buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1984
      {
1985
        if (mysql_errno(mysql) == ER_WRONG_OBJECT)
1986 1987 1988 1989 1990 1991
        {
          /* it is VIEW */
          fputs("\t\t<options Comment=\"view\" />\n", sql_file);
          goto continue_xml;
        }
        fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
1992
                my_progname, result_table, mysql_error(mysql));
1993
        if (path)
1994
          my_fclose(sql_file, MYF(MY_WME));
1995
        DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1996
      }
1997 1998 1999 2000

      /* Find first which key is primary key */
      keynr=0;
      primary_key=INT_MAX;
2001
      while ((row= mysql_fetch_row(result)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2002
      {
2003 2004
        if (atoi(row[3]) == 1)
        {
2005
          keynr++;
2006
#ifdef FORCE_PRIMARY_KEY
2007 2008
          if (atoi(row[1]) == 0 && primary_key == INT_MAX)
            primary_key=keynr;
2009
#endif
2010 2011 2012 2013 2014
          if (!strcmp(row[2],"PRIMARY"))
          {
            primary_key=keynr;
            break;
          }
2015
        }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2016
      }
2017
      mysql_data_seek(result,0);
2018
      keynr=0;
2019
      while ((row= mysql_fetch_row(result)))
2020
      {
2021 2022 2023 2024 2025
        if (opt_xml)
        {
          print_xml_row(sql_file, "key", result, &row);
          continue;
        }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2026

2027 2028
        if (atoi(row[3]) == 1)
        {
2029 2030 2031 2032 2033 2034 2035 2036 2037 2038
          if (keynr++)
            putc(')', sql_file);
          if (atoi(row[1]))       /* Test if duplicate key */
            /* Duplicate allowed */
            fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff,0));
          else if (keynr == primary_key)
            fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
          else
            fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff,
                                                            0));
2039 2040
        }
        else
2041
          putc(',', sql_file);
2042
        fputs(quote_name(row[4], name_buff, 0), sql_file);
2043
        if (row[7])
2044 2045
          fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
        check_io(sql_file);
2046
      }
2047 2048
      if (!opt_xml)
      {
2049 2050 2051 2052
        if (keynr)
          putc(')', sql_file);
        fputs("\n)",sql_file);
        check_io(sql_file);
2053
      }
2054 2055 2056

      /* Get MySQL specific create options */
      if (create_options)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2057
      {
2058
        char show_name_buff[NAME_LEN*2+2+24];
2059

2060
        /* Check memory for quote_for_like() */
2061
        my_snprintf(buff, sizeof(buff), "show table status like %s",
2062
                    quote_for_like(table, show_name_buff));
2063

2064
        if (mysql_query_with_error_report(mysql, &result, buff))
2065
        {
2066
          if (mysql_errno(mysql) != ER_PARSE_ERROR)
2067
          {                                     /* If old MySQL version */
2068
            verbose_msg("-- Warning: Couldn't get status information for " \
2069
                        "table %s (%s)\n", result_table,mysql_error(mysql));
2070
          }
2071
        }
2072
        else if (!(row= mysql_fetch_row(result)))
2073
        {
2074 2075
          fprintf(stderr,
                  "Error: Couldn't read status information for table %s (%s)\n",
2076
                  result_table,mysql_error(mysql));
2077 2078 2079
        }
        else
        {
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090
          if (opt_xml)
            print_xml_row(sql_file, "options", result, &row);
          else
          {
            fputs("/*!",sql_file);
            print_value(sql_file,result,row,"engine=","Engine",0);
            print_value(sql_file,result,row,"","Create_options",0);
            print_value(sql_file,result,row,"comment=","Comment",1);
            fputs(" */",sql_file);
            check_io(sql_file);
          }
2091
        }
2092
        mysql_free_result(result);              /* Is always safe to free */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2093
      }
2094
continue_xml:
2095
      if (!opt_xml)
2096
        fputs(";\n", sql_file);
2097
      else
2098
        fputs("\t</table_structure>\n", sql_file);
2099
      check_io(sql_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2100 2101
    }
  }
2102
  if (complete_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2103
  {
2104
    dynstr_append_checked(&insert_pat, ") VALUES ");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2105
    if (!extended_insert)
2106
      dynstr_append_checked(&insert_pat, "(");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2107
  }
2108
  if (sql_file != md_result_file)
2109 2110 2111
  {
    fputs("\n", sql_file);
    write_footer(sql_file);
2112
    my_fclose(sql_file, MYF(MY_WME));
2113
  }
2114
  DBUG_RETURN((uint) num_fields);
2115
} /* get_table_structure */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2116 2117


2118 2119 2120 2121 2122 2123 2124 2125 2126 2127
/*

  dump_triggers_for_table

  Dumps the triggers given a table/db name. This should be called after
  the tables have been dumped in case a trigger depends on the existence
  of a table

*/

2128 2129
static void dump_triggers_for_table(char *table,
                                    char *db __attribute__((unused)))
2130
{
2131 2132
  char       *result_table;
  char       name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
2133
  char       query_buff[512];
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2134
  uint old_opt_compatible_mode=opt_compatible_mode;
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2135
  FILE       *sql_file= md_result_file;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2136 2137
  MYSQL_RES  *result;
  MYSQL_ROW  row;
2138 2139
  DBUG_ENTER("dump_triggers_for_table");
  DBUG_PRINT("enter", ("db: %s, table: %s", db, table));
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2140 2141 2142

  /* Do not use ANSI_QUOTES on triggers in dump */
  opt_compatible_mode&= ~MASK_ANSI_QUOTES;
2143 2144 2145 2146 2147 2148
  result_table=     quote_name(table, table_buff, 1);

  my_snprintf(query_buff, sizeof(query_buff),
              "SHOW TRIGGERS LIKE %s",
              quote_for_like(table, name_buff));

2149
  if (mysql_query_with_error_report(mysql, &result, query_buff))
2150 2151 2152 2153 2154 2155
  {
    if (path)
      my_fclose(sql_file, MYF(MY_WME));
    DBUG_VOID_RETURN;
  }
  if (mysql_num_rows(result))
2156
  {
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
2157
    fprintf(sql_file, "\n/*!50003 SET @SAVE_SQL_MODE=@@SQL_MODE*/;\n");
2158 2159
    fprintf(sql_file, "\nDELIMITER ;;\n");
  }
2160
  while ((row= mysql_fetch_row(result)))
2161
  {
2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180
    fprintf(sql_file,
            "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n"
            "/*!50003 CREATE */ ",
            row[6] /* sql_mode */);

    if (mysql_num_fields(result) > 7)
    {
      /*
        mysqldump can be run against the server, that does not support definer
        in triggers (there is no DEFINER column in SHOW TRIGGERS output). So,
        we should check if we have this column before accessing it.
      */

      uint       user_name_len;
      char       user_name_str[USERNAME_LENGTH + 1];
      char       quoted_user_name_str[USERNAME_LENGTH * 2 + 3];
      uint       host_name_len;
      char       host_name_str[HOSTNAME_LENGTH + 1];
      char       quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
2181

2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192
      parse_user(row[7], strlen(row[7]), user_name_str, &user_name_len,
                 host_name_str, &host_name_len);

      fprintf(sql_file,
              "/*!50017 DEFINER=%s@%s */ ",
              quote_name(user_name_str, quoted_user_name_str, FALSE),
              quote_name(host_name_str, quoted_host_name_str, FALSE));
    }

    fprintf(sql_file,
            "/*!50003 TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n\n",
2193 2194 2195 2196
            quote_name(row[0], name_buff, 0), /* Trigger */
            row[4], /* Timing */
            row[1], /* Event */
            result_table,
2197
            (strchr(" \t\n\r", *(row[3]))) ? "" : " ",
2198 2199 2200
            row[3] /* Statement */);
  }
  if (mysql_num_rows(result))
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
2201
  {
2202
    fprintf(sql_file,
2203
            "DELIMITER ;\n"
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
2204 2205
            "/*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/;\n");
  }
2206
  mysql_free_result(result);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2207
  /*
2208
    make sure to set back opt_compatible mode to
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2209 2210 2211
    original value
  */
  opt_compatible_mode=old_opt_compatible_mode;
2212 2213 2214
  DBUG_VOID_RETURN;
}

2215 2216
static void add_load_option(DYNAMIC_STRING *str, const char *option,
                             const char *option_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2217
{
2218
  if (!option_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2219
  {
2220 2221
    /* Null value means we don't add this option. */
    return;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2222
  }
2223 2224 2225 2226 2227 2228 2229

  dynstr_append_checked(str, option);
  
  if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
  {
    /* It's a hex constant, don't escape */
    dynstr_append_checked(str, option_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2230
  }
2231 2232 2233 2234 2235 2236
  else
  {
    /* char constant; escape */
    field_escape(str, option_value);
  }
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2237 2238 2239


/*
2240 2241 2242 2243
  Allow the user to specify field terminator strings like:
  "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
  This is done by doubling ' and add a end -\ if needed to avoid
  syntax errors from the SQL parser.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2244 2245
*/

2246
static void field_escape(DYNAMIC_STRING* in, const char *from)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2247
{
2248
  uint end_backslashes= 0; 
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2249

2250
  dynstr_append_checked(in, "'");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2251

2252
  while (*from)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2253
  {
2254 2255
    dynstr_append_mem_checked(in, from, 1);

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2256 2257 2258 2259 2260
    if (*from == '\\')
      end_backslashes^=1;    /* find odd number of backslashes */
    else
    {
      if (*from == '\'' && !end_backslashes)
2261 2262 2263 2264
      {
        /* We want a duplicate of "'" for MySQL */
        dynstr_append_checked(in, "\'");
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2265 2266
      end_backslashes=0;
    }
2267
    from++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2268 2269 2270
  }
  /* Add missing backslashes if user has specified odd number of backs.*/
  if (end_backslashes)
2271 2272 2273 2274 2275
    dynstr_append_checked(in, "\\");
  
  dynstr_append_checked(in, "'");
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2276 2277


2278 2279 2280 2281 2282
static char *alloc_query_str(ulong size)
{
  char *query;

  if (!(query= (char*) my_malloc(size, MYF(MY_WME))))
2283 2284
    die(EX_MYSQLERR, "Couldn't allocate a query string.");

2285 2286 2287
  return query;
}

2288

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2289
/*
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301

 SYNOPSIS
  dump_table()

  dump_table saves database contents as a series of INSERT statements.

  ARGS
   table - table name
   db    - db name

   RETURNS
    void
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2302
*/
2303

2304

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2305
static void dump_table(char *table, char *db)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2306
{
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2307
  char ignore_flag;
2308 2309
  char buf[200], table_buff[NAME_LEN+3];
  DYNAMIC_STRING query_string;
monty@mysql.com's avatar
monty@mysql.com committed
2310
  char table_type[NAME_LEN];
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2311
  char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2312
  int error= 0;
2313
  ulong         rownr, row_break, total_length, init_length;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2314
  uint num_fields;
2315 2316 2317
  MYSQL_RES     *res;
  MYSQL_FIELD   *field;
  MYSQL_ROW     row;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2318 2319 2320 2321 2322 2323
  DBUG_ENTER("dump_table");

  /*
    Make sure you get the create table info before the following check for
    --no-data flag below. Otherwise, the create table info won't be printed.
  */
monty@mysql.com's avatar
monty@mysql.com committed
2324
  num_fields= get_table_structure(table, db, table_type, &ignore_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2325

2326 2327 2328 2329
  /*
    The "table" could be a view.  If so, we don't do anything here.
  */
  if (strcmp (table_type, "VIEW") == 0)
2330
    DBUG_VOID_RETURN;
2331

2332
  /* Check --no-data flag */
2333
  if (opt_no_data)
2334
  {
2335 2336
    verbose_msg("-- Skipping dump data for table '%s', --no-data was used\n",
                table);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2337
    DBUG_VOID_RETURN;
2338 2339
  }

monty@mysql.com's avatar
monty@mysql.com committed
2340 2341 2342
  DBUG_PRINT("info",
             ("ignore_flag: %x  num_fields: %d", (int) ignore_flag,
              num_fields));
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2343 2344 2345 2346 2347 2348
  /*
    If the table type is a merge table or any type that has to be
     _completely_ ignored and no data dumped
  */
  if (ignore_flag & IGNORE_DATA)
  {
2349 2350
    verbose_msg("-- Warning: Skipping data for table '%s' because " \
                "it's of type %s\n", table, table_type);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2351 2352
    DBUG_VOID_RETURN;
  }
2353
  /* Check that there are any fields in the table */
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2354
  if (num_fields == 0)
2355
  {
2356 2357
    verbose_msg("-- Skipping dump data for table '%s', it has no fields\n",
                table);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2358
    DBUG_VOID_RETURN;
2359 2360
  }

2361 2362
  result_table= quote_name(table,table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);
2363

2364
  verbose_msg("-- Sending SELECT query...\n");
2365 2366 2367

  init_dynamic_string_checked(&query_string, "", 1024, 1024);

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2368 2369 2370
  if (path)
  {
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
2371 2372 2373 2374 2375 2376

    /*
      Convert the path to native os format
      and resolve to the full filepath.
    */
    convert_dirname(tmp_path,path,NullS);    
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2377
    my_load_path(tmp_path, tmp_path, NULL);
2378 2379 2380 2381 2382 2383
    fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));

    /* Must delete the file that 'INTO OUTFILE' will write to */
    my_delete(filename, MYF(0));

    /* convert to a unix path name to stick into the query */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2384
    to_unix_path(filename);
2385 2386 2387 2388 2389 2390

    /* now build the query string */

    dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '");
    dynstr_append_checked(&query_string, filename);
    dynstr_append_checked(&query_string, "'");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2391 2392

    if (fields_terminated || enclosed || opt_enclosed || escaped)
2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
      dynstr_append_checked(&query_string, " FIELDS");
    
    add_load_option(&query_string, " TERMINATED BY ", fields_terminated);
    add_load_option(&query_string, " ENCLOSED BY ", enclosed);
    add_load_option(&query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
    add_load_option(&query_string, " ESCAPED BY ", escaped);
    add_load_option(&query_string, " LINES TERMINATED BY ", lines_terminated);

    dynstr_append_checked(&query_string, " FROM ");
    dynstr_append_checked(&query_string, result_table);

    if (where)
    {
      dynstr_append_checked(&query_string, " WHERE ");
      dynstr_append_checked(&query_string, where);
    }

    if (order_by)
    {
      dynstr_append_checked(&query_string, " ORDER BY ");
      dynstr_append_checked(&query_string, order_by);
    }

    if (mysql_real_query(mysql, query_string.str, query_string.length))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2417
    {
2418
      DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2419
      DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2420 2421 2422 2423
    }
  }
  else
  {
2424
    if (!opt_xml && opt_comments)
2425
    {
2426
      fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
2427
              result_table);
2428 2429
      check_io(md_result_file);
    }
2430 2431 2432
    
    dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM ");
    dynstr_append_checked(&query_string, result_table);
2433

2434 2435 2436
    if (where)
    {
      if (!opt_xml && opt_comments)
2437
      {
2438 2439
        fprintf(md_result_file, "-- WHERE:  %s\n", where);
        check_io(md_result_file);
2440
      }
2441 2442 2443 2444 2445 2446 2447
      
      dynstr_append_checked(&query_string, " WHERE ");
      dynstr_append_checked(&query_string, where);
    }
    if (order_by)
    {
      if (!opt_xml && opt_comments)
2448
      {
2449 2450
        fprintf(md_result_file, "-- ORDER BY:  %s\n", order_by);
        check_io(md_result_file);
2451
      }
2452 2453
      dynstr_append_checked(&query_string, " ORDER BY ");
      dynstr_append_checked(&query_string, order_by);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2454
    }
2455

2456
    if (!opt_xml && !opt_compact)
2457
    {
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2458
      fputs("\n", md_result_file);
2459 2460
      check_io(md_result_file);
    }
2461
    if (mysql_query_with_error_report(mysql, 0, query_string.str))
2462
    {
2463
      DB_error(mysql, "when retrieving data from server");
2464 2465
      goto err;
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2466
    if (quick)
2467
      res=mysql_use_result(mysql);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2468
    else
2469
      res=mysql_store_result(mysql);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2470
    if (!res)
2471
    {
2472
      DB_error(mysql, "when retrieving data from server");
2473 2474
      goto err;
    }
2475 2476

    verbose_msg("-- Retrieving rows...\n");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2477
    if (mysql_num_fields(res) != num_fields)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2478
    {
2479
      fprintf(stderr,"%s: Error in field count for table: %s !  Aborting.\n",
2480
              my_progname, result_table);
2481 2482
      error= EX_CONSCHECK;
      goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2483 2484
    }

2485
    if (opt_lock)
2486
    {
2487
      fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
2488 2489
      check_io(md_result_file);
    }
2490 2491
    /* Moved disable keys to after lock per bug 15977 */
    if (opt_disable_keys)
2492
    {
2493 2494
      fprintf(md_result_file, "/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
	      opt_quoted_table);
2495 2496
      check_io(md_result_file);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2497

2498
    total_length= opt_net_buffer_length;                /* Force row break */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2499 2500
    row_break=0;
    rownr=0;
2501
    init_length=(uint) insert_pat.length+4;
2502
    if (opt_xml)
2503 2504
      print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
              NullS);
2505
    if (opt_autocommit)
2506
    {
2507
      fprintf(md_result_file, "set autocommit=0;\n");
2508 2509
      check_io(md_result_file);
    }
2510

2511
    while ((row= mysql_fetch_row(res)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2512 2513
    {
      uint i;
2514
      ulong *lengths= mysql_fetch_lengths(res);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2515
      rownr++;
2516
      if (!extended_insert && !opt_xml)
2517
      {
2518 2519
        fputs(insert_pat.str,md_result_file);
        check_io(md_result_file);
2520
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2521 2522
      mysql_field_seek(res,0);

jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2523
      if (opt_xml)
2524
      {
2525
        fputs("\t<row>\n", md_result_file);
2526
        check_io(md_result_file);
2527
      }
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2528

grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2529
      for (i= 0; i < mysql_num_fields(res); i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2530
      {
2531
        int is_blob;
2532 2533
        ulong length= lengths[i];

grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2534
        if (!(field= mysql_fetch_field(res)))
2535 2536 2537
          die(EX_CONSCHECK,
                      "Not enough fields from table %s! Aborting.\n",
                      result_table);
2538 2539 2540 2541 2542 2543

        /*
           63 is my_charset_bin. If charsetnr is not 63,
           we have not a BLOB but a TEXT column.
           we'll dump in hex only BLOB columns.
        */
2544
        is_blob= (opt_hex_blob && field->charsetnr == 63 &&
2545 2546
                  (field->type == MYSQL_TYPE_BIT ||
                   field->type == MYSQL_TYPE_STRING ||
2547 2548 2549 2550 2551 2552
                   field->type == MYSQL_TYPE_VAR_STRING ||
                   field->type == MYSQL_TYPE_VARCHAR ||
                   field->type == MYSQL_TYPE_BLOB ||
                   field->type == MYSQL_TYPE_LONG_BLOB ||
                   field->type == MYSQL_TYPE_MEDIUM_BLOB ||
                   field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0;
2553
        if (extended_insert && !opt_xml)
2554 2555
        {
          if (i == 0)
2556
            dynstr_set_checked(&extended_row,"(");
2557
          else
2558
            dynstr_append_checked(&extended_row,",");
2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571

          if (row[i])
          {
            if (length)
            {
              if (!IS_NUM_FIELD(field))
              {
                /*
                  "length * 2 + 2" is OK for both HEX and non-HEX modes:
                  - In HEX mode we need exactly 2 bytes per character
                  plus 2 bytes for '0x' prefix.
                  - In non-HEX mode we need up to 2 bytes per character,
                  plus 2 bytes for leading and trailing '\'' characters.
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
2572
                  Also we need to reserve 1 byte for terminating '\0'.
2573
                */
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
2574
                dynstr_realloc_checked(&extended_row,length * 2 + 2 + 1);
2575 2576
                if (opt_hex_blob && is_blob)
                {
2577
                  dynstr_append_checked(&extended_row, "0x");
2578
                  extended_row.length+= mysql_hex_string(extended_row.str +
bar@mysql.com's avatar
bar@mysql.com committed
2579 2580
                                                         extended_row.length,
                                                         row[i], length);
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
2581 2582 2583
                  DBUG_ASSERT(extended_row.length+1 <= extended_row.max_length);
                  /* mysql_hex_string() already terminated string by '\0' */
                  DBUG_ASSERT(extended_row.str[extended_row.length] == '\0');
2584 2585 2586
                }
                else
                {
2587
                  dynstr_append_checked(&extended_row,"'");
2588 2589 2590 2591 2592
                  extended_row.length +=
                  mysql_real_escape_string(&mysql_connection,
                                           &extended_row.str[extended_row.length],
                                           row[i],length);
                  extended_row.str[extended_row.length]='\0';
2593
                  dynstr_append_checked(&extended_row,"'");
2594
                }
2595 2596 2597 2598
              }
              else
              {
                /* change any strings ("inf", "-inf", "nan") into NULL */
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2599
                char *ptr= row[i];
2600 2601
                if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
                    my_isalpha(charset_info, ptr[1])))
2602
                  dynstr_append_checked(&extended_row, "NULL");
2603 2604 2605 2606 2607
                else
                {
                  if (field->type == FIELD_TYPE_DECIMAL)
                  {
                    /* add " signs around */
2608 2609 2610
                    dynstr_append_checked(&extended_row, "'");
                    dynstr_append_checked(&extended_row, ptr);
                    dynstr_append_checked(&extended_row, "'");
2611 2612
                  }
                  else
2613
                    dynstr_append_checked(&extended_row, ptr);
2614 2615 2616 2617
                }
              }
            }
            else
2618
              dynstr_append_checked(&extended_row,"''");
2619
          }
2620 2621
          else
            dynstr_append_checked(&extended_row,"NULL");
2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635
        }
        else
        {
          if (i && !opt_xml)
          {
            fputc(',', md_result_file);
            check_io(md_result_file);
          }
          if (row[i])
          {
            if (!IS_NUM_FIELD(field))
            {
              if (opt_xml)
              {
2636 2637
                if (opt_hex_blob && is_blob && length)
                {
2638 2639 2640 2641
                  /* Define xsi:type="xs:hexBinary" for hex encoded data */
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
                                field->name, "xsi:type=", "xs:hexBinary", NullS);
                  print_blob_as_hex(md_result_file, row[i], length);
2642 2643 2644
                }
                else
                {
2645 2646 2647
                  print_xml_tag(md_result_file, "\t\t", "", "field", "name=", 
                                field->name, NullS);
                  print_quoted_xml(md_result_file, row[i], length);
2648
                }
2649 2650 2651
                fputs("</field>\n", md_result_file);
              }
              else if (opt_hex_blob && is_blob && length)
monty@mysql.com's avatar
monty@mysql.com committed
2652
              {
2653
                fputs("0x", md_result_file);
2654
                print_blob_as_hex(md_result_file, row[i], length);
2655 2656
              }
              else
2657
                unescape(md_result_file, row[i], length);
2658 2659 2660 2661
            }
            else
            {
              /* change any strings ("inf", "-inf", "nan") into NULL */
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2662
              char *ptr= row[i];
2663 2664
              if (opt_xml)
              {
2665 2666
                print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
                        field->name, NullS);
2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685
                fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
                      md_result_file);
                fputs("</field>\n", md_result_file);
              }
              else if (my_isalpha(charset_info, *ptr) ||
                       (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
                fputs("NULL", md_result_file);
              else if (field->type == FIELD_TYPE_DECIMAL)
              {
                /* add " signs around */
                fputc('\'', md_result_file);
                fputs(ptr, md_result_file);
                fputc('\'', md_result_file);
              }
              else
                fputs(ptr, md_result_file);
            }
          }
          else
2686 2687 2688 2689 2690 2691 2692 2693
          {
            /* The field value is NULL */
            if (!opt_xml)
              fputs("NULL", md_result_file);
            else
              print_xml_null_tag(md_result_file, "\t\t", "field name=",
                                 field->name, "\n");
          }
vva@eagle.mysql.r18.ru's avatar
Merge  
vva@eagle.mysql.r18.ru committed
2694
          check_io(md_result_file);
2695
        }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2696 2697
      }

jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2698
      if (opt_xml)
2699
      {
2700
        fputs("\t</row>\n", md_result_file);
2701
        check_io(md_result_file);
2702
      }
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2703

2704
      if (extended_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2705
      {
2706
        ulong row_length;
2707
        dynstr_append_checked(&extended_row,")");
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2708
        row_length= 2 + extended_row.length;
2709
        if (total_length + row_length < opt_net_buffer_length)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2710
        {
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2711
          total_length+= row_length;
2712 2713 2714
          fputc(',',md_result_file);            /* Always row break */
          fputs(extended_row.str,md_result_file);
        }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2715 2716
        else
        {
2717 2718 2719
          if (row_break)
            fputs(";\n", md_result_file);
          row_break=1;                          /* This is first row */
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2720

2721
          fputs(insert_pat.str,md_result_file);
2722
          fputs(extended_row.str,md_result_file);
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2723
          total_length= row_length+init_length;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2724
        }
2725
        check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2726
      }
2727
      else if (!opt_xml)
2728
      {
2729 2730
        fputs(");\n", md_result_file);
        check_io(md_result_file);
2731
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2732
    }
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2733

2734
    /* XML - close table tag and supress regular output */
2735
    if (opt_xml)
2736
        fputs("\t</table_data>\n", md_result_file);
2737
    else if (extended_insert && row_break)
2738
      fputs(";\n", md_result_file);             /* If not empty table */
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2739
    fflush(md_result_file);
2740
    check_io(md_result_file);
2741
    if (mysql_errno(mysql))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2742
    {
2743
      my_snprintf(buf, sizeof(buf),
2744 2745
                  "%s: Error %d: %s when dumping table %s at row: %ld\n",
                  my_progname,
2746 2747
                  mysql_errno(mysql),
                  mysql_error(mysql),
2748 2749
                  result_table,
                  rownr);
2750
      fputs(buf,stderr);
2751 2752
      error= EX_CONSCHECK;
      goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2753
    }
2754 2755

    /* Moved enable keys to before unlock per bug 15977 */
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2756
    if (opt_disable_keys)
2757
    {
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2758
      fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
2759
              opt_quoted_table);
2760 2761
      check_io(md_result_file);
    }
2762 2763 2764 2765 2766
    if (opt_lock)
    {
      fputs("UNLOCK TABLES;\n", md_result_file);
      check_io(md_result_file);
    }
2767
    if (opt_autocommit)
2768
    {
2769
      fprintf(md_result_file, "commit;\n");
2770 2771
      check_io(md_result_file);
    }
2772
    mysql_free_result(res);
2773
    dynstr_free(&query_string);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2774 2775
  }
  DBUG_VOID_RETURN;
2776 2777

err:
2778 2779
  dynstr_free(&query_string);
  maybe_exit(error);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2780
  DBUG_VOID_RETURN;
2781
} /* dump_table */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2782 2783 2784 2785


static char *getTableName(int reset)
{
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2786
  static MYSQL_RES *res= NULL;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2787 2788 2789 2790
  MYSQL_ROW    row;

  if (!res)
  {
2791
    if (!(res= mysql_list_tables(mysql,NullS)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2792 2793
      return(NULL);
  }
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2794
  if ((row= mysql_fetch_row(res)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2795
    return((char*) row[0]);
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
2796

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2797 2798 2799 2800 2801
  if (reset)
    mysql_data_seek(res,0);      /* We want to read again */
  else
  {
    mysql_free_result(res);
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2802
    res= NULL;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813
  }
  return(NULL);
} /* getTableName */


static int dump_all_databases()
{
  MYSQL_ROW row;
  MYSQL_RES *tableres;
  int result=0;

2814
  if (mysql_query_with_error_report(mysql, &tableres, "SHOW DATABASES"))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2815
    return 1;
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2816
  while ((row= mysql_fetch_row(tableres)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2817 2818 2819 2820
  {
    if (dump_all_tables_in_db(row[0]))
      result=1;
  }
2821
  if (seen_views)
2822
  {
2823
    if (mysql_query(mysql, "SHOW DATABASES") ||
2824
        !(tableres= mysql_store_result(mysql)))
2825 2826
    {
      my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
2827
                      MYF(0), mysql_error(mysql));
2828 2829
      return 1;
    }
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
2830
    while ((row= mysql_fetch_row(tableres)))
2831 2832 2833 2834 2835
    {
      if (dump_all_views_in_db(row[0]))
        result=1;
    }
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2836 2837 2838 2839 2840 2841 2842 2843
  return result;
}
/* dump_all_databases */


static int dump_databases(char **db_names)
{
  int result=0;
2844
  char **db;
2845 2846
  DBUG_ENTER("dump_databases");

2847
  for (db= db_names ; *db ; db++)
2848
  {
2849
    if (dump_all_tables_in_db(*db))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2850 2851
      result=1;
  }
2852
  if (!result && seen_views)
2853 2854 2855 2856 2857 2858 2859
  {
    for (db= db_names ; *db ; db++)
    {
      if (dump_all_views_in_db(*db))
        result=1;
    }
  }
2860
  DBUG_RETURN(result);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2861 2862 2863
} /* dump_databases */


2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874
/*
View Specific database initalization.

SYNOPSIS
  init_dumping_views
  qdatabase      quoted name of the database

RETURN VALUES
  0        Success.
  1        Failure.
*/
2875
int init_dumping_views(char *qdatabase __attribute__((unused)))
2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908
{
    return 0;
} /* init_dumping_views */


/*
Table Specific database initalization.

SYNOPSIS
  init_dumping_tables
  qdatabase      quoted name of the database

RETURN VALUES
  0        Success.
  1        Failure.
*/
int init_dumping_tables(char *qdatabase)
{
  if (!opt_create_db)
  {
    char qbuf[256];
    MYSQL_ROW row;
    MYSQL_RES *dbinfo;

    my_snprintf(qbuf, sizeof(qbuf),
                "SHOW CREATE DATABASE IF NOT EXISTS %s",
                qdatabase);

    if (mysql_query(mysql, qbuf) || !(dbinfo = mysql_store_result(mysql)))
    {
      /* Old server version, dump generic CREATE DATABASE */
      if (opt_drop_database)
        fprintf(md_result_file,
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
2909
                "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933
                qdatabase);
      fprintf(md_result_file,
              "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
              qdatabase);
    }
    else
    {
      if (opt_drop_database)
        fprintf(md_result_file,
                "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
                qdatabase);
      row = mysql_fetch_row(dbinfo);
      if (row[1])
      {
        fprintf(md_result_file,"\n%s;\n",row[1]);
      }
    }
  }

  return 0;
} /* init_dumping_tables */


static int init_dumping(char *database, int init_func(char*))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2934
{
2935
  if (mysql_get_server_version(mysql) >= 50003 &&
2936
      !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
2937
    return 1;
2938

2939
  if (mysql_select_db(mysql, database))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2940
  {
2941
    DB_error(mysql, "when selecting the database");
2942
    return 1;                   /* If --force */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2943
  }
2944
  if (!path && !opt_xml)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2945 2946 2947
  {
    if (opt_databases || opt_alldbs)
    {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2948
      /*
2949
        length of table name * 2 (if name contains quotes), 2 quotes and 0
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2950
      */
2951
      char quoted_database_buf[NAME_LEN*2+3];
2952
      char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
2953
      if (opt_comments)
2954
      {
2955 2956
        fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
        check_io(md_result_file);
2957
      }
2958

2959 2960
      /* Call the view or table specific function */
      init_func(qdatabase);
2961

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2962
      fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
2963
      check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2964 2965
    }
  }
2966 2967
  if (extended_insert)
    init_dynamic_string_checked(&extended_row, "", 1024, 1024);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2968 2969 2970 2971
  return 0;
} /* init_dumping */


2972 2973
/* Return 1 if we should copy the table */

2974 2975
my_bool include_table(byte* hash_key, uint len)
{
2976
  return !hash_search(&ignore_table, (byte*) hash_key, len);
2977 2978
}

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2979

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2980 2981 2982 2983
static int dump_all_tables_in_db(char *database)
{
  char *table;
  uint numrows;
2984
  char table_buff[NAME_LEN*2+3];
2985 2986
  char hash_key[2*NAME_LEN+2];  /* "db.tablename" */
  char *afterdot;
2987
  int using_mysql_db= my_strcasecmp(&my_charset_latin1, database, "mysql");
2988
  DBUG_ENTER("dump_all_tables_in_db");
2989 2990 2991 2992

  afterdot= strmov(hash_key, database);
  *afterdot++= '.';

2993
  if (init_dumping(database, init_dumping_tables))
2994
    DBUG_RETURN(1);
2995
  if (opt_xml)
2996
    print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2997 2998 2999
  if (lock_tables)
  {
    DYNAMIC_STRING query;
3000
    init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
3001
    for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3002
    {
3003 3004
      dynstr_append_checked(&query, quote_name(table, table_buff, 1));
      dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3005
    }
3006 3007
    if (numrows && mysql_real_query(mysql, query.str, query.length-1))
      DB_error(mysql, "when using LOCK TABLES");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3008 3009 3010 3011 3012
            /* We shall continue here, if --force was given */
    dynstr_free(&query);
  }
  if (flush_logs)
  {
3013 3014
    if (mysql_refresh(mysql, REFRESH_LOG))
      DB_error(mysql, "when doing refresh");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3015 3016
           /* We shall continue here, if --force was given */
  }
3017
  while ((table= getTableName(0)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3018
  {
3019 3020 3021
    char *end= strmov(afterdot, table);
    if (include_table(hash_key, end - hash_key))
    {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3022
      dump_table(table,database);
3023 3024
      my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
      order_by= 0;
3025
      if (opt_dump_triggers && ! opt_xml &&
3026
          mysql_get_server_version(mysql) >= 50009)
3027
        dump_triggers_for_table(table, database);
3028
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3029
  }
3030
  if (opt_routines && !opt_xml &&
3031
      mysql_get_server_version(mysql) >= 50009)
3032 3033 3034 3035
  {
    DBUG_PRINT("info", ("Dumping routines for database %s", database));
    dump_routines_for_db(database);
  }
3036
  if (opt_xml)
3037
  {
3038
    fputs("</database>\n", md_result_file);
3039 3040
    check_io(md_result_file);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3041
  if (lock_tables)
3042
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
3043 3044 3045 3046 3047
  if (flush_privileges && using_mysql_db == 0)
  {
    fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n");
    fprintf(md_result_file,"\n/*! FLUSH PRIVILEGES */;\n");
  }
3048
  DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3049 3050 3051
} /* dump_all_tables_in_db */


3052 3053 3054 3055 3056 3057
/*
   dump structure of views of database

   SYNOPSIS
     dump_all_views_in_db()
     database  database name
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3058

3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069
  RETURN
    0 OK
    1 ERROR
*/

static my_bool dump_all_views_in_db(char *database)
{
  char *table;
  uint numrows;
  char table_buff[NAME_LEN*2+3];

3070
  if (init_dumping(database, init_dumping_views))
3071
    return 1;
3072
  if (opt_xml)
3073
    print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
3074 3075 3076
  if (lock_tables)
  {
    DYNAMIC_STRING query;
3077
    init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
3078 3079
    for (numrows= 0 ; (table= getTableName(1)); numrows++)
    {
3080 3081
      dynstr_append_checked(&query, quote_name(table, table_buff, 1));
      dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
3082
    }
3083 3084
    if (numrows && mysql_real_query(mysql, query.str, query.length-1))
      DB_error(mysql, "when using LOCK TABLES");
3085 3086 3087 3088 3089
            /* We shall continue here, if --force was given */
    dynstr_free(&query);
  }
  if (flush_logs)
  {
3090 3091
    if (mysql_refresh(mysql, REFRESH_LOG))
      DB_error(mysql, "when doing refresh");
3092 3093 3094
           /* We shall continue here, if --force was given */
  }
  while ((table= getTableName(0)))
3095
     get_view_structure(table, database);
3096 3097 3098 3099 3100 3101
  if (opt_xml)
  {
    fputs("</database>\n", md_result_file);
    check_io(md_result_file);
  }
  if (lock_tables)
3102
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
3103 3104
  return 0;
} /* dump_all_tables_in_db */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3105

gluh@gluh.mysql.r18.ru's avatar
gluh@gluh.mysql.r18.ru committed
3106

3107
/*
3108 3109 3110
  get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
  table name from the server for the table name given on the command line.
  we do this because the table name given on the command line may be a
3111
  different case (e.g.  T1 vs t1)
3112

3113
  RETURN
ramil@mysql.com's avatar
ramil@mysql.com committed
3114 3115
    pointer to the table name
    0 if error
3116 3117
*/

ramil@mysql.com's avatar
ramil@mysql.com committed
3118
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
3119
{
ramil@mysql.com's avatar
ramil@mysql.com committed
3120
  char *name= 0;
3121
  MYSQL_RES  *table_res;
3122
  MYSQL_ROW  row;
3123
  char query[50 + 2*NAME_LEN];
3124
  char show_name_buff[FN_REFLEN];
3125
  DBUG_ENTER("get_actual_table_name");
3126

3127 3128
  /* Check memory for quote_for_like() */
  DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
3129
  my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
3130
              quote_for_like(old_table_name, show_name_buff));
3131

3132
  if (mysql_query_with_error_report(mysql, 0, query))
3133
    return NullS;
3134

3135
  if ((table_res= mysql_store_result(mysql)))
3136
  {
3137 3138 3139
    my_ulonglong num_rows= mysql_num_rows(table_res);
    if (num_rows > 0)
    {
ramil@mysql.com's avatar
ramil@mysql.com committed
3140
      ulong *lengths;
3141 3142 3143 3144 3145
      /*
        Return first row
        TODO: Return all matching rows
      */
      row= mysql_fetch_row(table_res);
ramil@mysql.com's avatar
ramil@mysql.com committed
3146
      lengths= mysql_fetch_lengths(table_res);
ramil@mysql.com's avatar
ramil@mysql.com committed
3147
      name= strmake_root(root, row[0], lengths[0]);
3148 3149
    }
    mysql_free_result(table_res);
3150
  }
ramil@mysql.com's avatar
ramil@mysql.com committed
3151 3152
  DBUG_PRINT("exit", ("new_table_name: %s", name));
  DBUG_RETURN(name);
3153
}
3154

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3155 3156 3157

static int dump_selected_tables(char *db, char **table_names, int tables)
{
3158
  char table_buff[NAME_LEN*+3];
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3159
  DYNAMIC_STRING lock_tables_query;
ramil@mysql.com's avatar
ramil@mysql.com committed
3160 3161
  MEM_ROOT root;
  char **dump_tables, **pos, **end;
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3162
  DBUG_ENTER("dump_selected_tables");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3163

3164
  if (init_dumping(db, init_dumping_tables))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3165
    return 1;
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3166

ramil@mysql.com's avatar
ramil@mysql.com committed
3167 3168
  init_alloc_root(&root, 8192, 0);
  if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
3169
     die(EX_EOM, "alloc_root failure.");
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3170

3171
  init_dynamic_string_checked(&lock_tables_query, "LOCK TABLES ", 256, 1024);
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3172
  for (; tables > 0 ; tables-- , table_names++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3173
  {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3174
    /* the table name passed on commandline may be wrong case */
ramil@mysql.com's avatar
ramil@mysql.com committed
3175
    if ((*pos= get_actual_table_name(*table_names, &root)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3176
    {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3177 3178 3179
      /* Add found table name to lock_tables_query */
      if (lock_tables)
      {
3180 3181
        dynstr_append_checked(&lock_tables_query, quote_name(*pos, table_buff, 1));
        dynstr_append_checked(&lock_tables_query, " READ /*!32311 LOCAL */,");
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3182
      }
ramil@mysql.com's avatar
ramil@mysql.com committed
3183
      pos++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3184
    }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3185
    else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3186
    {
3187
       maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3188
       /* We shall countinue here, if --force was given */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3189
    }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3190
  }
ramil@mysql.com's avatar
ramil@mysql.com committed
3191
  end= pos;
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3192 3193 3194

  if (lock_tables)
  {
3195
    if (mysql_real_query(mysql, lock_tables_query.str,
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3196
                         lock_tables_query.length-1))
3197
      DB_error(mysql, "when doing LOCK TABLES");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3198 3199
       /* We shall countinue here, if --force was given */
  }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3200
  dynstr_free(&lock_tables_query);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3201 3202
  if (flush_logs)
  {
3203 3204
    if (mysql_refresh(mysql, REFRESH_LOG))
      DB_error(mysql, "when doing refresh");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3205 3206
     /* We shall countinue here, if --force was given */
  }
3207
  if (opt_xml)
3208
    print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NullS);
3209

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3210
  /* Dump each selected table */
ramil@mysql.com's avatar
ramil@mysql.com committed
3211
  for (pos= dump_tables; pos < end; pos++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3212
  {
ramil@mysql.com's avatar
ramil@mysql.com committed
3213 3214
    DBUG_PRINT("info",("Dumping table %s", *pos));
    dump_table(*pos, db);
3215
    if (opt_dump_triggers &&
3216
        mysql_get_server_version(mysql) >= 50009)
ramil@mysql.com's avatar
ramil@mysql.com committed
3217
      dump_triggers_for_table(*pos, db);
3218
  }
3219 3220

  /* Dump each selected view */
3221
  if (seen_views)
3222
  {
ramil@mysql.com's avatar
ramil@mysql.com committed
3223 3224
    for (pos= dump_tables; pos < end; pos++)
      get_view_structure(*pos, db);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3225
  }
3226 3227
  /* obtain dump of routines (procs/functions) */
  if (opt_routines  && !opt_xml &&
3228
      mysql_get_server_version(mysql) >= 50009)
3229 3230 3231 3232
  {
    DBUG_PRINT("info", ("Dumping routines for database %s", db));
    dump_routines_for_db(db);
  }
ramil@mysql.com's avatar
ramil@mysql.com committed
3233
  free_root(&root, MYF(0));
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3234 3235
  my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
  order_by= 0;
3236
  if (opt_xml)
3237
  {
3238
    fputs("</database>\n", md_result_file);
3239 3240
    check_io(md_result_file);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3241
  if (lock_tables)
3242
    VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
3243
  DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3244 3245 3246
} /* dump_selected_tables */


3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258
static int do_show_master_status(MYSQL *mysql_con)
{
  MYSQL_ROW row;
  MYSQL_RES *master;
  const char *comment_prefix=
    (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
  if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
  {
    return 1;
  }
  else
  {
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3259
    row= mysql_fetch_row(master);
3260 3261
    if (row && row[0] && row[1])
    {
3262
      /* SHOW MASTER STATUS reports file and position */
3263 3264 3265 3266 3267 3268
      if (opt_comments)
        fprintf(md_result_file,
                "\n--\n-- Position to start replication or point-in-time "
                "recovery from\n--\n\n");
      fprintf(md_result_file,
              "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
3269
              comment_prefix, row[0], row[1]);
3270 3271
      check_io(md_result_file);
    }
3272 3273 3274
    else if (!ignore_errors)
    {
      /* SHOW MASTER STATUS reports nothing and --force is not enabled */
3275 3276
      my_printf_error(0, "Error: Binlogging on server not active",
                      MYF(0));
3277 3278 3279
      mysql_free_result(master);
      return 1;
    }
3280 3281 3282 3283 3284 3285 3286 3287
    mysql_free_result(master);
  }
  return 0;
}


static int do_flush_tables_read_lock(MYSQL *mysql_con)
{
3288 3289 3290 3291 3292 3293 3294 3295
  /*
    We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
    will wait but will not stall the whole mysqld, and when the long update is
    done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
    FLUSH TABLES is to lower the probability of a stage where both mysqldump
    and most client connections are stalled. Of course, if a second long
    update starts between the two FLUSHes, we have that bad stall.
  */
3296
  return
3297 3298 3299
    ( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") ||
      mysql_query_with_error_report(mysql_con, 0,
                                    "FLUSH TABLES WITH READ LOCK") );
3300 3301 3302 3303 3304 3305 3306 3307
}


static int do_unlock_tables(MYSQL *mysql_con)
{
  return mysql_query_with_error_report(mysql_con, 0, "UNLOCK TABLES");
}

tsmith@quadxeon.mysql.com's avatar
tsmith@quadxeon.mysql.com committed
3308 3309
static int get_bin_log_name(MYSQL *mysql_con,
                            char* buff_log_name, uint buff_len)
3310 3311 3312 3313
{
  MYSQL_RES *res;
  MYSQL_ROW row;

tsmith@quadxeon.mysql.com's avatar
tsmith@quadxeon.mysql.com committed
3314
  if (mysql_query(mysql_con, "SHOW MASTER STATUS") ||
3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327
      !(res= mysql_store_result(mysql)))
    return 1;

  if (!(row= mysql_fetch_row(res)))
  {
    mysql_free_result(res);
    return 1;
  }
  /*
    Only one row is returned, and the first column is the name of the
    active log.
  */
  strmake(buff_log_name, row[0], buff_len - 1);
3328

3329 3330 3331 3332 3333
  mysql_free_result(res);
  return 0;
}

static int purge_bin_logs_to(MYSQL *mysql_con, char* log_name)
3334
{
3335 3336 3337 3338 3339 3340 3341 3342
  DYNAMIC_STRING str;
  int err;
  init_dynamic_string_checked(&str, "PURGE BINARY LOGS TO '", 1024, 1024);
  dynstr_append_checked(&str, log_name);
  dynstr_append_checked(&str, "'");
  err = mysql_query_with_error_report(mysql_con, 0, str.str);
  dynstr_free(&str);
  return err;
3343 3344 3345
}


3346
static int start_transaction(MYSQL *mysql_con)
3347 3348 3349 3350 3351
{
  /*
    We use BEGIN for old servers. --single-transaction --master-data will fail
    on old servers, but that's ok as it was already silently broken (it didn't
    do a consistent read, so better tell people frankly, with the error).
3352 3353 3354 3355

    We want the first consistent read to be used for all tables to dump so we
    need the REPEATABLE READ level (not anything lower, for example READ
    COMMITTED would give one new consistent read per dumped table).
3356 3357
  */
  return (mysql_query_with_error_report(mysql_con, 0,
3358 3359 3360
                                        "SET SESSION TRANSACTION ISOLATION "
                                        "LEVEL REPEATABLE READ") ||
          mysql_query_with_error_report(mysql_con, 0,
3361
                                        "START TRANSACTION "
3362
                                        "/*!40100 WITH CONSISTENT SNAPSHOT */"));
3363 3364
}

3365 3366

static ulong find_set(TYPELIB *lib, const char *x, uint length,
3367
                      char **err_pos, uint *err_len)
3368 3369 3370 3371 3372 3373
{
  const char *end= x + length;
  ulong found= 0;
  uint find;
  char buff[255];

3374
  *err_pos= 0;                  /* No error yet */
3375
  while (end > x && my_isspace(charset_info, end[-1]))
3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406
    end--;

  *err_len= 0;
  if (x != end)
  {
    const char *start= x;
    for (;;)
    {
      const char *pos= start;
      uint var_len;

      for (; pos != end && *pos != ','; pos++) ;
      var_len= (uint) (pos - start);
      strmake(buff, start, min(sizeof(buff), var_len));
      find= find_type(buff, lib, var_len);
      if (!find)
      {
        *err_pos= (char*) start;
        *err_len= var_len;
      }
      else
        found|= ((longlong) 1 << (find - 1));
      if (pos == end)
        break;
      start= pos + 1;
    }
  }
  return found;
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
3407 3408
/* Print a value with a prefix on file */
static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
3409 3410
                        const char *prefix, const char *name,
                        int string_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3411
{
3412
  MYSQL_FIELD   *field;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3413 3414
  mysql_field_seek(result, 0);

grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3415
  for ( ; (field= mysql_fetch_field(result)) ; row++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3416 3417 3418 3419 3420
  {
    if (!strcmp(field->name,name))
    {
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
      {
3421 3422 3423 3424 3425 3426 3427 3428
        fputc(' ',file);
        fputs(prefix, file);
        if (string_value)
          unescape(file,row[0],(uint) strlen(row[0]));
        else
          fputs(row[0], file);
        check_io(file);
        return;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3429 3430 3431
      }
    }
  }
3432
  return;                                       /* This shouldn't happen */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3433 3434 3435
} /* print_value */


3436 3437
/*
  SYNOPSIS
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3438 3439 3440 3441

  Check if we the table is one of the table types that should be ignored:
  MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts.
  If the table should be altogether ignored, it returns a TRUE, FALSE if it
3442 3443
  should not be ignored. If the user has selected to use INSERT DELAYED, it
  sets the value of the bool pointer supports_delayed_inserts to 0 if not
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3444 3445 3446 3447
  supported, 1 if it is supported.

  ARGS

3448
    check_if_ignore_table()
3449
    table_name                  Table name to check
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3450
    table_type                  Type of table
3451 3452

  GLOBAL VARIABLES
3453
    mysql                       MySQL connection
3454
    verbose                     Write warning messages
3455 3456

  RETURN
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3457
    char (bit value)            See IGNORE_ values at top
3458 3459
*/

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3460
char check_if_ignore_table(const char *table_name, char *table_type)
3461
{
3462
  char result= IGNORE_NONE;
3463
  char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
dkatz/Damien@damiendev's avatar
dkatz/Damien@damiendev committed
3464
  MYSQL_RES *res= NULL;
3465
  MYSQL_ROW row;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3466
  DBUG_ENTER("check_if_ignore_table");
3467

3468 3469 3470
  /* Check memory for quote_for_like() */
  DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff));
  my_snprintf(buff, sizeof(buff), "show table status like %s",
3471
              quote_for_like(table_name, show_name_buff));
3472
  if (mysql_query_with_error_report(mysql, &res, buff))
3473
  {
3474
    if (mysql_errno(mysql) != ER_PARSE_ERROR)
3475
    {                                   /* If old MySQL version */
3476 3477
      verbose_msg("-- Warning: Couldn't get status information for "
                  "table %s (%s)\n", table_name, mysql_error(mysql));
3478
      DBUG_RETURN(result);                       /* assume table is ok */
3479 3480
    }
  }
3481
  if (!(row= mysql_fetch_row(res)))
3482 3483
  {
    fprintf(stderr,
3484
            "Error: Couldn't read status information for table %s (%s)\n",
3485
            table_name, mysql_error(mysql));
3486
    mysql_free_result(res);
3487
    DBUG_RETURN(result);                         /* assume table is ok */
3488
  }
3489
  if (!(row[1]))
monty@mysql.com's avatar
monty@mysql.com committed
3490
    strmake(table_type, "VIEW", NAME_LEN-1);
3491 3492
  else
  {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3493 3494 3495 3496 3497 3498
    /*
      If the table type matches any of these, we do support delayed inserts.
      Note: we do not want to skip dumping this table if if is not one of
      these types, but we do want to use delayed inserts in the dump if
      the table type is _NOT_ one of these types
    */
3499
    strmake(table_type, row[1], NAME_LEN-1);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512
    if (opt_delayed)
    {
      if (strcmp(table_type,"MyISAM") &&
          strcmp(table_type,"ISAM") &&
          strcmp(table_type,"ARCHIVE") &&
          strcmp(table_type,"HEAP") &&
          strcmp(table_type,"MEMORY"))
        result= IGNORE_INSERT_DELAYED;
    }

    /*
      If these two types, we do want to skip dumping the table
    */
3513
    if (!opt_no_data &&
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3514 3515
        (!strcmp(table_type,"MRG_MyISAM") || !strcmp(table_type,"MRG_ISAM")))
      result= IGNORE_DATA;
3516
  }
3517
  mysql_free_result(res);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3518
  DBUG_RETURN(result);
3519 3520
}

3521

3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538
/*
  Get string of comma-separated primary key field names

  SYNOPSIS
    char *primary_key_fields(const char *table_name)
    RETURNS     pointer to allocated buffer (must be freed by caller)
    table_name  quoted table name

  DESCRIPTION
    Use SHOW KEYS FROM table_name, allocate a buffer to hold the
    field names, and then build that string and return the pointer
    to that buffer.

    Returns NULL if there is no PRIMARY or UNIQUE key on the table,
    or if there is some failure.  It is better to continue to dump
    the table unsorted, rather than exit without dumping the data.
*/
monty@mishka.local's avatar
monty@mishka.local committed
3539

3540 3541
static char *primary_key_fields(const char *table_name)
{
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3542
  MYSQL_RES  *res= NULL;
3543 3544
  MYSQL_ROW  row;
  /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
3545
  char show_keys_buff[15 + NAME_LEN * 2 + 3];
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3546 3547
  uint result_length= 0;
  char *result= 0;
3548 3549
  char buff[NAME_LEN * 2 + 3];
  char *quoted_field;
3550

3551 3552
  my_snprintf(show_keys_buff, sizeof(show_keys_buff),
              "SHOW KEYS FROM %s", table_name);
3553
  if (mysql_query(mysql, show_keys_buff) ||
3554
      !(res= mysql_store_result(mysql)))
3555 3556 3557
  {
    fprintf(stderr, "Warning: Couldn't read keys from table %s;"
            " records are NOT sorted (%s)\n",
3558
            table_name, mysql_error(mysql));
3559 3560 3561 3562
    /* Don't exit, because it's better to print out unsorted records */
    goto cleanup;
  }

tsmith@build.mysql.com's avatar
tsmith@build.mysql.com committed
3563 3564 3565 3566 3567 3568
  /*
   * Figure out the length of the ORDER BY clause result.
   * Note that SHOW KEYS is ordered:  a PRIMARY key is always the first
   * row, and UNIQUE keys come before others.  So we only need to check
   * the first key, not all keys.
   */
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3569
  if ((row= mysql_fetch_row(res)) && atoi(row[1]) == 0)
3570
  {
tsmith@build.mysql.com's avatar
tsmith@build.mysql.com committed
3571 3572
    /* Key is unique */
    do
3573 3574 3575 3576
    {
      quoted_field= quote_name(row[4], buff, 0);
      result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
    } while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1);
3577 3578 3579
  }

  /* Build the ORDER BY clause result */
monty@mishka.local's avatar
monty@mishka.local committed
3580 3581
  if (result_length)
  {
3582 3583
    char *end;
    /* result (terminating \0 is already in result_length) */
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3584
    result= my_malloc(result_length + 10, MYF(MY_WME));
monty@mishka.local's avatar
monty@mishka.local committed
3585 3586
    if (!result)
    {
3587 3588 3589
      fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n");
      goto cleanup;
    }
tsmith@build.mysql.com's avatar
tsmith@build.mysql.com committed
3590
    mysql_data_seek(res, 0);
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3591
    row= mysql_fetch_row(res);
3592 3593
    quoted_field= quote_name(row[4], buff, 0);
    end= strmov(result, quoted_field);
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3594
    while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1)
3595 3596 3597 3598
    {
      quoted_field= quote_name(row[4], buff, 0);
      end= strxmov(end, ",", quoted_field, NullS);
    }
3599 3600 3601 3602 3603 3604 3605 3606 3607
  }

cleanup:
  if (res)
    mysql_free_result(res);

  return result;
}

3608

3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628
/*
  Replace a substring

  SYNOPSIS
    replace
    ds_str      The string to search and perform the replace in
    search_str  The string to search for
    search_len  Length of the string to search for
    replace_str The string to replace with
    replace_len Length of the string to replace with

  RETURN
    0 String replaced
    1 Could not find search_str in str
*/

static int replace(DYNAMIC_STRING *ds_str,
                   const char *search_str, ulong search_len,
                   const char *replace_str, ulong replace_len)
{
msvensson@neptunus.(none)'s avatar
msvensson@neptunus.(none) committed
3629
  DYNAMIC_STRING ds_tmp;
3630 3631 3632
  const char *start= strstr(ds_str->str, search_str);
  if (!start)
    return 1;
3633
  init_dynamic_string_checked(&ds_tmp, "",
3634
                      ds_str->length + replace_len, 256);
3635 3636 3637 3638
  dynstr_append_mem_checked(&ds_tmp, ds_str->str, start - ds_str->str);
  dynstr_append_mem_checked(&ds_tmp, replace_str, replace_len);
  dynstr_append_checked(&ds_tmp, start + search_len);
  dynstr_set_checked(ds_str, ds_tmp.str);
3639 3640 3641 3642 3643
  dynstr_free(&ds_tmp);
  return 0;
}


3644 3645 3646 3647
/*
  Getting VIEW structure

  SYNOPSIS
3648
    get_view_structure()
3649 3650 3651 3652 3653 3654 3655 3656
    table   view name
    db      db name

  RETURN
    0 OK
    1 ERROR
*/

3657
static my_bool get_view_structure(char *table, char* db)
3658
{
3659
  MYSQL_RES  *table_res;
3660 3661
  MYSQL_ROW  row;
  MYSQL_FIELD *field;
3662 3663 3664
  char       *result_table, *opt_quoted_table;
  char       table_buff[NAME_LEN*2+3];
  char       table_buff2[NAME_LEN*2+3];
3665
  char       query[QUERY_LENGTH];
grog@eucla.lemis.com's avatar
grog@eucla.lemis.com committed
3666
  FILE       *sql_file= md_result_file;
3667
  DBUG_ENTER("get_view_structure");
3668

3669
  if (opt_no_create_info) /* Don't write table creation info */
3670 3671
    DBUG_RETURN(0);

3672
  verbose_msg("-- Retrieving view structure for table %s...\n", table);
3673

jimw@mysql.com's avatar
jimw@mysql.com committed
3674
#ifdef NOT_REALLY_USED_YET
3675
  sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
3676
          (opt_quoted || opt_keywords));
jimw@mysql.com's avatar
jimw@mysql.com committed
3677 3678
#endif

3679 3680 3681
  result_table=     quote_name(table, table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);

3682
  my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %s", result_table);
3683
  if (mysql_query_with_error_report(mysql, &table_res, query))
3684 3685
    DBUG_RETURN(0);

3686 3687 3688 3689
  /* Check if this is a view */
  field= mysql_fetch_field_direct(table_res, 0);
  if (strcmp(field->name, "View") != 0)
  {
3690
    verbose_msg("-- It's base table, skipped\n");
3691 3692 3693 3694
    DBUG_RETURN(0);
  }

  /* If requested, open separate .sql file for this view */
3695 3696
  if (path)
  {
3697
    if (!(sql_file= open_sql_file_for_table(table)))
3698
      DBUG_RETURN(1);
3699

3700 3701 3702 3703 3704
    write_header(sql_file, db);
  }

  if (!opt_xml && opt_comments)
  {
3705
    fprintf(sql_file, "\n--\n-- Final view structure for view %s\n--\n\n",
3706 3707 3708
            result_table);
    check_io(sql_file);
  }
gshchepa/uchum@gleb.loc's avatar
gshchepa/uchum@gleb.loc committed
3709
  fprintf(sql_file, "/*!50001 DROP TABLE %s*/;\n", opt_quoted_table);
3710 3711
  if (opt_drop)
  {
3712 3713
    fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
            opt_quoted_table);
3714 3715 3716 3717
    check_io(sql_file);
  }


3718 3719 3720 3721
  my_snprintf(query, sizeof(query),
              "SELECT CHECK_OPTION, DEFINER, SECURITY_TYPE "            \
              "FROM information_schema.views "                          \
              "WHERE table_name=\"%s\" AND table_schema=\"%s\"", table, db);
3722
  if (mysql_query(mysql, query))
3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743
  {
    /*
      Use the raw output from SHOW CREATE TABLE if
       information_schema query fails.
     */
    row= mysql_fetch_row(table_res);
    fprintf(sql_file, "/*!50001 %s */;\n", row[1]);
    check_io(sql_file);
    mysql_free_result(table_res);
  }
  else
  {
    char *ptr;
    ulong *lengths;
    char search_buf[256], replace_buf[256];
    ulong search_len, replace_len;
    DYNAMIC_STRING ds_view;

    /* Save the result of SHOW CREATE TABLE in ds_view */
    row= mysql_fetch_row(table_res);
    lengths= mysql_fetch_lengths(table_res);
3744
    init_dynamic_string_checked(&ds_view, row[1], lengths[1] + 1, 1024);
3745 3746 3747
    mysql_free_result(table_res);

    /* Get the result from "select ... information_schema" */
3748
    if (!(table_res= mysql_store_result(mysql)) ||
3749
        !(row= mysql_fetch_row(table_res)))
3750
    {
3751
      DB_error(mysql, "when trying to save the result of SHOW CREATE TABLE in ds_view.");
3752 3753
      DBUG_RETURN(1);
    }
3754

3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785
    lengths= mysql_fetch_lengths(table_res);

    /*
      "WITH %s CHECK OPTION" is available from 5.0.2
      Surround it with !50002 comments
    */
    if (strcmp(row[0], "NONE"))
    {

      ptr= search_buf;
      search_len= (ulong)(strxmov(ptr, "WITH ", row[0],
                                  " CHECK OPTION", NullS) - ptr);
      ptr= replace_buf;
      replace_len=(ulong)(strxmov(ptr, "*/\n/*!50002 WITH ", row[0],
                                  " CHECK OPTION", NullS) - ptr);
      replace(&ds_view, search_buf, search_len, replace_buf, replace_len);
    }

    /*
      "DEFINER=%s SQL SECURITY %s" is available from 5.0.13
      Surround it with !50013 comments
    */
    {
      uint       user_name_len;
      char       user_name_str[USERNAME_LENGTH + 1];
      char       quoted_user_name_str[USERNAME_LENGTH * 2 + 3];
      uint       host_name_len;
      char       host_name_str[HOSTNAME_LENGTH + 1];
      char       quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];

      parse_user(row[1], lengths[1], user_name_str, &user_name_len,
3786
                 host_name_str, &host_name_len);
3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813

      ptr= search_buf;
      search_len=
        (ulong)(strxmov(ptr, "DEFINER=",
                        quote_name(user_name_str, quoted_user_name_str, FALSE),
                        "@",
                        quote_name(host_name_str, quoted_host_name_str, FALSE),
                        " SQL SECURITY ", row[2], NullS) - ptr);
      ptr= replace_buf;
      replace_len=
        (ulong)(strxmov(ptr, "*/\n/*!50013 DEFINER=",
                        quote_name(user_name_str, quoted_user_name_str, FALSE),
                        "@",
                        quote_name(host_name_str, quoted_host_name_str, FALSE),
                        " SQL SECURITY ", row[2],
                        " */\n/*!50001", NullS) - ptr);
      replace(&ds_view, search_buf, search_len, replace_buf, replace_len);
    }

    /* Dump view structure to file */
    fprintf(sql_file, "/*!50001 %s */;\n", ds_view.str);
    check_io(sql_file);
    mysql_free_result(table_res);
    dynstr_free(&ds_view);
  }

  /* If a separate .sql file was opened, close it now */
3814 3815 3816 3817 3818 3819 3820 3821 3822
  if (sql_file != md_result_file)
  {
    fputs("\n", sql_file);
    write_footer(sql_file);
    my_fclose(sql_file, MYF(MY_WME));
  }
  DBUG_RETURN(0);
}

3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861
/*
  The following functions are wrappers for the dynamic string functions
  and if they fail, the wrappers will terminate the current process.
*/

#define DYNAMIC_STR_ERROR_MSG "Couldn't perform DYNAMIC_STRING operation"

static void init_dynamic_string_checked(DYNAMIC_STRING *str, const char *init_str,
			    uint init_alloc, uint alloc_increment)
{
  if (init_dynamic_string(str, init_str, init_alloc, alloc_increment))
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
}

static void dynstr_append_checked(DYNAMIC_STRING* dest, const char* src)
{
  if (dynstr_append(dest, src))
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
}

static void dynstr_set_checked(DYNAMIC_STRING *str, const char *init_str)
{
  if (dynstr_set(str, init_str))
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
}

static void dynstr_append_mem_checked(DYNAMIC_STRING *str, const char *append,
			  uint length)
{
  if (dynstr_append_mem(str, append, length))
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
}

static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size)
{
  if (dynstr_realloc(str, additional_size))
    die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
}

3862

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3863 3864
int main(int argc, char **argv)
{
3865
  char bin_log_name[FN_REFLEN];
3866
  int exit_code;
3867 3868
  MY_INIT("mysqldump");

3869
  compatible_mode_normal_str[0]= 0;
3870
  default_charset= (char *)mysql_universal_client_charset;
monty@mishka.local's avatar
monty@mishka.local committed
3871
  bzero((char*) &ignore_table, sizeof(ignore_table));
3872

3873 3874
  exit_code= get_options(&argc, &argv);
  if (exit_code)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3875
  {
3876 3877
    free_resources(0);
    exit(exit_code);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3878
  }
3879 3880 3881 3882 3883 3884 3885 3886 3887 3888

  if (log_error_file)
  {
    if(!(stderror_file= freopen(log_error_file, "a+", stderr)))
    {
      free_resources(0);
      exit(EX_MYSQLERR);
    }
  }

3889 3890 3891
  if (connect_to_db(current_host, current_user, opt_password))
  {
    free_resources(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3892
    exit(EX_MYSQLERR);
3893
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3894
  if (!path)
3895 3896
    write_header(md_result_file, *argv);

3897
  if ((opt_lock_all_tables || opt_master_data) &&
3898
      do_flush_tables_read_lock(mysql))
3899
    goto err;
3900
  if (opt_single_transaction && start_transaction(mysql))
3901
      goto err;
3902 3903 3904 3905 3906 3907 3908
  if (opt_delete_master_logs)
  {
    if (mysql_refresh(mysql, REFRESH_LOG) ||
        get_bin_log_name(mysql, bin_log_name, sizeof(bin_log_name)))
      goto err;
    flush_logs= 0;
  }
3909
  if (opt_lock_all_tables || opt_master_data)
3910
  {
3911
    if (flush_logs && mysql_refresh(mysql, REFRESH_LOG))
3912 3913
      goto err;
    flush_logs= 0; /* not anymore; that would not be sensible */
3914
  }
3915
  if (opt_master_data && do_show_master_status(mysql))
3916
    goto err;
3917
  if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */
3918 3919
    goto err;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3920 3921 3922
  if (opt_alldbs)
    dump_all_databases();
  else if (argc > 1 && !opt_databases)
3923 3924
  {
    /* Only one database and selected table(s) */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3925
    dump_selected_tables(*argv, (argv + 1), (argc - 1));
3926
  }
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
3927
  else
3928 3929
  {
    /* One or more databases, all tables */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3930
    dump_databases(argv);
3931
  }
3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943

  /* ensure dumped data flushed */
  if (md_result_file && fflush(md_result_file))
  {
    if (!first_error)
      first_error= EX_MYSQLERR;
    goto err;
  }
  /* everything successful, purge the old logs files */
  if (opt_delete_master_logs && purge_bin_logs_to(mysql, bin_log_name))
    goto err;

3944 3945 3946
#ifdef HAVE_SMEM
  my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif
3947 3948 3949 3950 3951 3952 3953
  /*
    No reason to explicitely COMMIT the transaction, neither to explicitely
    UNLOCK TABLES: these will be automatically be done by the server when we
    disconnect now. Saves some code here, some network trips, adds nothing to
    server.
  */
err:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3954
  dbDisconnect(current_host);
3955 3956
  if (!path)
    write_footer(md_result_file);
3957
  free_resources();
3958 3959 3960 3961

  if (stderror_file)
    fclose(stderror_file);

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3962 3963
  return(first_error);
} /* main */