mysqldump.c 100 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 5 6
   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
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
7

bk@work.mysql.com's avatar
bk@work.mysql.com committed
8 9 10 11
   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.
12

bk@work.mysql.com's avatar
bk@work.mysql.com committed
13 14 15 16 17 18 19 20
   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 :-
**
21 22 23 24 25 26 27 28 29 30 31 32
** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
** DATE:   December 3, 1994
** WARRANTY: None, expressed, impressed, implied
**	    or other
** 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>
monty@mysql.com's avatar
monty@mysql.com committed
33
** Tõnu Samuel  <tonu@please.do.not.remove.this.spam.ee>
34 35
** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up
** and adapted to mysqldump 05/11/01 by Jani Tolonen
36
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
37
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
38
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
39

40
#define DUMP_VERSION "10.10"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
41

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

48
#include "client_priv.h"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
49 50 51 52 53 54 55 56 57 58
#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
59
#define EX_EOF 5 /* ferror for output file was got */
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
60
#define EX_ILLEGAL_TABLE 6
bk@work.mysql.com's avatar
bk@work.mysql.com committed
61 62 63 64 65 66 67 68 69

/* 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

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

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
73 74 75 76 77
/* 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 */

bk@work.mysql.com's avatar
bk@work.mysql.com committed
78 79
static char *add_load_option(char *ptr, const char *object,
			     const char *statement);
80 81
static ulong find_set(TYPELIB *lib, const char *x, uint length,
		      char **err_pos, uint *err_len);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
82 83

static char *field_escape(char *to,const char *from,uint length);
84
static my_bool  verbose=0,tFlag=0,dFlag=0,quick= 1, extended_insert= 1,
85 86
		lock_tables=1,ignore_errors=0,flush_logs=0,
		opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
87
                opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
jimw@mysql.com's avatar
jimw@mysql.com committed
88 89
                opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,
                opt_set_charset=0,
90
		opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
monty@mysql.com's avatar
monty@mysql.com committed
91
		opt_delete_master_logs=0, tty_password=0,
92
		opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
jimw@mysql.com's avatar
jimw@mysql.com committed
93
		opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
94
                opt_complete_insert= 0, opt_drop_database= 0,
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
95
                opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1;
96
static ulong opt_max_allowed_packet, opt_net_buffer_length;
monty@mysql.com's avatar
monty@mysql.com committed
97
static MYSQL mysql_connection,*sock=0;
98 99 100
static my_bool insert_pat_inited=0;
static DYNAMIC_STRING insert_pat;
static char  *opt_password=0,*current_user=0,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
101 102
             *current_host=0,*path=0,*fields_terminated=0,
             *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
103
             *where=0, *order_by=0,
104
             *opt_compatible_mode_str= 0,
105
             *err_ptr= 0;
106
static char compatible_mode_normal_str[255];
107
static ulong opt_compatible_mode= 0;
108 109 110
#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
static uint     opt_mysql_port= 0, err_len= 0, opt_master_data;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
111 112 113
static my_string opt_mysql_unix_port=0;
static int   first_error=0;
static DYNAMIC_STRING extended_row;
114
#include <sslopt-vars.h>
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
115
FILE  *md_result_file;
116 117 118
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
#endif
119
static uint opt_protocol= 0;
120
/*
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
121 122 123
  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().
124
*/
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
125
static const char *mysql_universal_client_charset=
126 127
  MYSQL_UNIVERSAL_CLIENT_CHARSET;
static char *default_charset;
128
static CHARSET_INFO *charset_info= &my_charset_latin1;
129
const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace";
130 131
/* do we met VIEWs during tables scaning */
my_bool was_views= 0;
132 133 134 135

const char *compatible_mode_names[]=
{
  "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
136 137
  "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
  "ANSI",
138 139
  NullS
};
140 141 142 143 144 145 146 147 148
#define MASK_ANSI_QUOTES \
(\
 (1<<2)  | /* POSTGRESQL */\
 (1<<3)  | /* ORACLE     */\
 (1<<4)  | /* MSSQL      */\
 (1<<5)  | /* DB2        */\
 (1<<6)  | /* MAXDB      */\
 (1<<10)   /* ANSI       */\
)
149
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
bar@mysql.com's avatar
bar@mysql.com committed
150
				  "", compatible_mode_names, NULL};
151

152
HASH ignore_table;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
153

154
static struct my_option my_long_options[] =
bk@work.mysql.com's avatar
bk@work.mysql.com committed
155
{
156 157 158
  {"all", 'a', "Deprecated. Use --create-options instead.",
   (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
   0, 0, 0, 0, 0},
159 160 161 162
  {"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},
163 164 165
  {"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},
166
  {"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
167
   (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
168 169
   0},
  {"add-locks", OPT_LOCKS, "Add locks around insert statements.",
170
   (gptr*) &opt_lock, (gptr*) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
171 172 173 174
   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},
175 176 177 178
#ifdef __NETWARE__
  {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
179
  {"character-sets-dir", OPT_CHARSETS_DIR,
180
   "Directory where character sets are.", (gptr*) &charsets_dir,
181
   (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
182 183 184
  {"comments", 'i', "Write additional information.",
   (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
   1, 0, 0, 0, 0, 0},
185
  {"compatible", OPT_COMPATIBLE,
monty@mishka.local's avatar
monty@mishka.local committed
186
   "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.",
187 188
   (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0,
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
189
  {"compact", OPT_COMPACT,
serg@serg.mylan's avatar
serg@serg.mylan committed
190
   "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",
191 192
   (gptr*) &opt_compact, (gptr*) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
193 194 195
  {"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},
196 197 198
  {"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
199 200 201 202
  {"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},
203 204 205 206
  {"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},
207 208 209 210 211 212 213
#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
214 215 216
  {"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
217
  {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ",
218 219
   (gptr*) &opt_delayed, (gptr*) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
220
  {"delete-master-logs", OPT_DELETE_MASTER_LOGS,
221 222 223
   "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},
224 225
  {"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,
226
   (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
227 228 229
  {"extended-insert", 'e',
   "Allows utilization of the new, much faster INSERT syntax.",
   (gptr*) &extended_insert, (gptr*) &extended_insert, 0, GET_BOOL, NO_ARG,
230
   1, 0, 0, 0, 0, 0},
231 232 233 234 235 236 237 238 239 240
  {"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
241
   (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
242 243
  {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
   (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
244
   0, 0, 0, 0, 0, 0},
serg@serg.mylan's avatar
serg@serg.mylan committed
245
  {"flush-logs", 'F', "Flush logs file in server before starting dump. "
246 247 248 249 250 251 252 253
   "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",
254 255 256 257 258 259 260
   (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
   0, 0},
  {"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
261 262 263
  {"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},
264
  {"host", 'h', "Connect to host.", (gptr*) &current_host,
265
   (gptr*) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
266 267 268 269 270
  {"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},
271 272 273
  {"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},
274 275 276
  {"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},
277 278 279 280 281
  {"lock-all-tables", 'x', "Locks all tables across all databases. This " 
   "is achieved by taking a global read lock for the duration of the whole "
   "dump. Automatically turns --single-transaction 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},
282
  {"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables,
283
   (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
284
  {"master-data", OPT_MASTER_DATA,
285 286 287 288 289 290 291 292 293 294
   "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,
295
   GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
monty@mysql.com's avatar
monty@mysql.com committed
296 297 298 299 300 301 302 303
  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
    (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0,
    GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096, 
   (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},
304 305 306 307 308
  {"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',
309
   "'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.}.",
310 311 312
   (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.",
313 314 315
   (gptr*) &tFlag, (gptr*) &tFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"no-data", 'd', "No row information.", (gptr*) &dFlag, (gptr*) &dFlag, 0,
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
316
  {"no-set-names", 'N',
317
   "Deprecated. Use --skip-set-charset instead.",
318
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
319
  {"opt", OPT_OPTIMIZE,
320
   "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.",
321
   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
322 323 324
  {"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},
325 326 327
  {"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
328
#ifdef __WIN__
329
  {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
330
   NO_ARG, 0, 0, 0, 0, 0, 0},
bk@work.mysql.com's avatar
bk@work.mysql.com committed
331
#endif
332 333 334
  {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
   (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
   0},
335
  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
336
   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
337
  {"quick", 'q', "Don't buffer query, dump directly to stdout.",
338
   (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
339
  {"quote-names",'Q', "Quote table and column names with backticks (`).",
340
   (gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
341 342
   0, 0},
  {"result-file", 'r',
serg@sergbook.mysql.com's avatar
serg@sergbook.mysql.com committed
343
   "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).",
344
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
paul@frost.snake.net's avatar
paul@frost.snake.net committed
345
  {"routines", 'R', "Dump stored routines (functions and procedures).",
346 347
     (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
348 349 350 351
  {"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},
352 353 354
  {"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},
355
#ifdef HAVE_SMEM
356
  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
357
   "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
358 359
   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
monty@mysql.com's avatar
monty@mysql.com committed
360 361 362 363 364
  /*
    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.
  */
365
  {"single-transaction", OPT_TRANSACTION,
monty@mysql.com's avatar
monty@mysql.com committed
366 367 368 369 370 371 372
   "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},
373
  {"skip-opt", OPT_SKIP_OPTIMIZATION,
374
   "Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
375
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
376 377 378
  {"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},
379
#include <sslopt-longopts.h>
380 381 382 383 384
  {"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},
385
   {"triggers", OPT_TRIGGERS, "Dump triggers for each dumped table",
386 387
     (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
388
  {"tz-utc", OPT_TZ_UTC,
389
    "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
390
    (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
391
#ifndef DONT_ALLOW_USER_CHANGE
392 393 394
  {"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
395
#endif
396 397 398 399 400 401 402 403
  {"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},
404
  {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
405 406 407 408 409
};

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

static void safe_exit(int error);
410
static void write_header(FILE *sql_file, char *db_name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
411 412 413 414 415 416 417 418
static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
			const char *prefix,const char *name,
			int string_value);
static int dump_selected_tables(char *db, char **table_names, int tables);
static int dump_all_tables_in_db(char *db);
static int init_dumping(char *);
static int dump_databases(char **);
static int dump_all_databases();
419
static char *quote_name(const char *name, char *buff, my_bool force);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
420
char check_if_ignore_table(const char *table_name, char *table_type);
421
static char *primary_key_fields(const char *table_name);
422
static my_bool get_view_structure(char *table, char* db);
423
static my_bool dump_all_views_in_db(char *database);
424

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

427 428 429 430 431 432 433 434 435 436 437 438 439
/*
  exit with message if ferror(file)
  
  SYNOPSIS
    check_io()
    file	- checked file
*/

void check_io(FILE *file)
{
  if (ferror(file))
  {
    fprintf(stderr, "%s: Got errno %d on write\n", my_progname, errno);
440
    ignore_errors= 0; /* We can't ignore this error */
441 442 443 444
    safe_exit(EX_EOF);
  }
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
445 446 447
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
448 449
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
  NETWARE_SET_SCREEN_MODE(1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
450 451 452
} /* print_version */


453 454 455 456 457 458
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",
	 my_progname);
  printf("OR     %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
monty@mysql.com's avatar
monty@mysql.com committed
459
  NETWARE_SET_SCREEN_MODE(1);
460 461
}

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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
463 464 465 466 467 468
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");
469
  short_usage_sub();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
470
  print_defaults("my",load_default_groups);
471 472
  my_print_help(my_long_options);
  my_print_variables(my_long_options);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
473 474 475
} /* usage */


476 477 478 479 480 481
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
482 483
#include <help_end.h>

484

485
static void write_header(FILE *sql_file, char *db_name)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
486
{
487
  if (opt_xml)
488
  {
489
    fputs("<?xml version=\"1.0\"?>\n", sql_file);
490 491 492 493
    fputs("<mysqldump ", sql_file);
    fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
          sql_file);
    fputs(">\n", sql_file);
494
    check_io(sql_file);
495
  }
496
  else if (!opt_compact)
497
  {
498 499 500 501 502 503 504 505 506 507 508
    if (opt_comments)
    {
      fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
      fprintf(sql_file, "-- Host: %s    Database: %s\n",
	      current_host ? current_host : "localhost", db_name ? db_name :
	      "");
      fputs("-- ------------------------------------------------------\n",
	    sql_file);
      fprintf(sql_file, "-- Server version\t%s\n",
	      mysql_get_server_info(&mysql_connection));
    }
509
    if (opt_set_charset)
bar@bar.intranet.mysql.r18.ru's avatar
bar@bar.intranet.mysql.r18.ru committed
510 511 512 513 514
      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
515 516 517 518 519 520 521

    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");
    }

522 523 524
    if (!path)
    {
      fprintf(md_result_file,"\
525 526 527
/*!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\
");
528 529
    }
    fprintf(sql_file,
530 531
	    "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='%s%s%s' */;\n"
	    "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n",
vva@eagle.mysql.r18.ru's avatar
Merge  
vva@eagle.mysql.r18.ru committed
532 533
	    path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",",
	    compatible_mode_normal_str);
534
    check_io(sql_file);
535
  }
536
} /* write_header */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
537

538

539 540 541
static void write_footer(FILE *sql_file)
{
  if (opt_xml)
542
  {
543
    fputs("</mysqldump>\n", sql_file);
544 545
    check_io(sql_file);
  }
546
  else if (!opt_compact)
547
  {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
548 549 550
    if (opt_tz_utc)
      fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n");

551 552 553 554
    fprintf(sql_file,"\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n");
    if (!path)
    {
      fprintf(md_result_file,"\
555
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
556
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
557
    }
558
    if (opt_set_charset)
559
      fprintf(sql_file,
bar@bar.intranet.mysql.r18.ru's avatar
bar@bar.intranet.mysql.r18.ru committed
560 561 562
"/*!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");
563
    fprintf(sql_file,
564
	    "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
565
    fputs("\n", sql_file);
566
    check_io(sql_file);
567
  }
568
} /* write_footer */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
569

monty@mishka.local's avatar
monty@mishka.local committed
570 571 572 573 574 575
static void free_table_ent(char *key)

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

576

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
577 578
byte* get_table_key(const char *entry, uint *length,
				my_bool not_used __attribute__((unused)))
579
{
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
580 581
  *length= strlen(entry);
  return (byte*) entry;
582 583 584
}


serg@serg.mylan's avatar
serg@serg.mylan committed
585
void init_table_rule_hash(HASH* h)
586
{
monty@mishka.local's avatar
monty@mishka.local committed
587 588 589
  if (hash_init(h, charset_info, 16, 0, 0,
                (hash_get_key) get_table_key,
                (hash_free_key) free_table_ent, 0))
serg@serg.mylan's avatar
serg@serg.mylan committed
590
    exit(EX_EOM);
591 592
}

593 594 595
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
	       char *argument)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
596
{
597
  switch (optid) {
598 599 600 601 602
#ifdef __NETWARE__
  case OPT_AUTO_CLOSE:
    setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
    break;
#endif
603 604 605 606 607 608 609 610 611
  case 'p':
    if (argument)
    {
      char *start=argument;
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
      opt_password=my_strdup(argument,MYF(MY_FAE));
      while (*argument) *argument++= 'x';		/* Destroy argument */
      if (*start)
	start[1]=0;				/* Cut length of argument */
612
      tty_password= 0;
613 614 615 616 617
    }
    else
      tty_password=1;
    break;
  case 'r':
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
618
    if (!(md_result_file = my_fopen(argument, O_WRONLY | FILE_BINARY,
619 620 621 622
				    MYF(MY_WME))))
      exit(1);
    break;
  case 'W':
bk@work.mysql.com's avatar
bk@work.mysql.com committed
623
#ifdef __WIN__
624
    opt_protocol = MYSQL_PROTOCOL_PIPE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
625
#endif
626
    break;
627 628 629
  case 'N':
    opt_set_charset= 0;
    break;
630 631 632 633
  case 'T':
    opt_disable_keys=0;
    break;
  case '#':
634
    DBUG_PUSH(argument ? argument : default_dbug_option);
635
    break;
636
#include <sslopt-case.h>
637 638 639
  case 'V': print_version(); exit(0);
  case 'X':
    opt_xml = 1;
640 641
    extended_insert= opt_drop= opt_lock= 
      opt_disable_keys= opt_autocommit= opt_create_db= 0;
642 643 644 645 646
    break;
  case 'I':
  case '?':
    usage();
    exit(0);
647 648 649 650
  case (int) OPT_MASTER_DATA:
    if (!argument) /* work like in old versions */
      opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
    break;
651
  case (int) OPT_OPTIMIZE:
652
    extended_insert= opt_drop= opt_lock= quick= create_options=
653
      opt_disable_keys= lock_tables= opt_set_charset= 1;
654
    break;
655 656
  case (int) OPT_SKIP_OPTIMIZATION:
    extended_insert= opt_drop= opt_lock= quick= create_options=
monty@mishka.local's avatar
monty@mishka.local committed
657
      opt_disable_keys= lock_tables= opt_set_charset= 0;
658
    break;
659 660 661 662
  case (int) OPT_COMPACT:
  if (opt_compact)
  {
    opt_comments= opt_drop= opt_disable_keys= opt_lock= 0;
663
    opt_set_charset= 0;
664
  }
665 666 667
  case (int) OPT_TABLES:
    opt_databases=0;
    break;
668 669
  case (int) OPT_IGNORE_TABLE:
  {
serg@serg.mylan's avatar
serg@serg.mylan committed
670
    if (!strchr(argument, '.'))
671
    {
serg@serg.mylan's avatar
serg@serg.mylan committed
672
      fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n");
673 674
      exit(1);
    }
serg@serg.mylan's avatar
serg@serg.mylan committed
675 676 677
    if (!hash_inited(&ignore_table))
      init_table_rule_hash(&ignore_table);

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
678
    if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0))))
serg@serg.mylan's avatar
serg@serg.mylan committed
679
      exit(EX_EOM);
680 681
    break;
  }
682
  case (int) OPT_COMPATIBLE:
serg@serg.mylan's avatar
serg@serg.mylan committed
683
    {
684
      char buff[255];
685 686 687
      char *end= compatible_mode_normal_str;
      int i;
      ulong mode;
688 689

      opt_quoted= 1;
690
      opt_set_charset= 0;
691 692 693 694 695 696 697 698 699 700
      opt_compatible_mode_str= argument;
      opt_compatible_mode= find_set(&compatible_mode_typelib,
				    argument, strlen(argument),
				    &err_ptr, &err_len);
      if (err_len)
      {
	strmake(buff, err_ptr, min(sizeof(buff), err_len));
	fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
	exit(1);
      }
701 702
#if !defined(DBUG_OFF)
      {
monty@mysql.com's avatar
monty@mysql.com committed
703
	uint size_for_sql_mode= 0;
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
	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);
      }
#endif
      mode= opt_compatible_mode;
      for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++)
      {
	if (mode & 1)
	{
	  end= strmov(end, compatible_mode_names[i]);
	  end= strmov(end, ",");
	}
      }
      if (end!=compatible_mode_normal_str)
	end[-1]= 0;
722 723 724 725
      /* 
        Set charset to the default compiled value if it hasn't
        been reset yet by --default-character-set=xxx.
      */
726
      if (default_charset == mysql_universal_client_charset)
727
        default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
728 729 730
      break;
    }
  case (int) OPT_MYSQL_PROTOCOL:
731
    {
732
      if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0)
733 734 735 736 737
      {
	fprintf(stderr, "Unknown option to protocol: %s\n", argument);
	exit(1);
      }
      break;
738
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
739
  }
740 741 742 743 744 745
  return 0;
}

static int get_options(int *argc, char ***argv)
{
  int ho_error;
746 747 748 749
  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;
750 751 752 753

  md_result_file= stdout;
  load_defaults("my",load_default_groups,argc,argv);

754
  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
755
    exit(ho_error);
756

757 758 759
  *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
760 761 762 763 764
  if (opt_delayed)
    opt_lock=0;				/* Can't have lock with delayed */
  if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
		fields_terminated))
  {
765 766
    fprintf(stderr,
	    "%s: You must use option --tab with --fields-...\n", my_progname);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
767 768
    return(1);
  }
769 770 771 772 773 774 775 776 777 778 779 780 781

  /* 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);
    return(1);
  }  
  if (opt_master_data)
    opt_lock_all_tables= !opt_single_transaction;
  if (opt_single_transaction || opt_lock_all_tables)
782
    lock_tables= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
783 784 785 786 787 788 789 790 791 792 793 794
  if (enclosed && opt_enclosed)
  {
    fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
    return(1);
  }
  if ((opt_databases || opt_alldbs) && path)
  {
    fprintf(stderr,
	    "%s: --databases or --all-databases can't be used with --tab.\n",
	    my_progname);
    return(1);
  }
795 796
  if (strcmp(default_charset, charset_info->csname) &&
      !(charset_info= get_charset_by_csname(default_charset, 
797
  					    MY_CS_PRIMARY, MYF(MY_WME))))
798
    exit(1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
799 800
  if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
  {
801
    short_usage();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
802 803 804
    return 1;
  }
  if (tty_password)
805
    opt_password=get_tty_password(NullS);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
806 807 808 809 810
  return(0);
} /* get_options */


/*
811
** DB_error -- prints mysql error message and exits the program.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
812
*/
813
static void DB_error(MYSQL *mysql, const char *when)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
814
{
815
  DBUG_ENTER("DB_error");
816
  my_printf_error(0,"Got error: %d: %s %s", MYF(0),
bk@work.mysql.com's avatar
bk@work.mysql.com committed
817 818 819
		  mysql_errno(mysql), mysql_error(mysql), when);
  safe_exit(EX_MYSQLERR);
  DBUG_VOID_RETURN;
820
} /* DB_error */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
821 822


823 824 825 826 827 828 829
/*
  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
830 831
    res             if non zero, result will be put there with
		    mysql_store_result()
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
    query           query to send to server

  RETURN VALUES
    0               query sending and (if res!=0) result reading went ok
    1               error
*/
  
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))))
  {
    my_printf_error(0, "%s: Couldn't execute '%s': %s (%d)",
                    MYF(0), my_progname, query,
                    mysql_error(mysql_con), mysql_errno(mysql_con));
    return 1;
  }
  return 0;
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
static void safe_exit(int error)
{
  if (!first_error)
    first_error= error;
  if (ignore_errors)
    return;
  if (sock)
    mysql_close(sock);
  exit(error);
}
/* safe_exit */


/*
** dbConnect -- connects to the host and selects DB.
*/
static int dbConnect(char *host, char *user,char *passwd)
{
872
  char buff[20+FN_REFLEN];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
873 874 875
  DBUG_ENTER("dbConnect");
  if (verbose)
  {
876
    fprintf(stderr, "-- Connecting to %s...\n", host ? host : "localhost");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
877 878 879 880 881 882 883
  }
  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,
884
		  opt_ssl_capath, opt_ssl_cipher);
885 886 887 888 889 890
#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
891
#endif
892
  mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
893 894 895 896
  if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd,
         NULL,opt_mysql_port,opt_mysql_unix_port,
         0)))
  {
897
    DB_error(&mysql_connection, "when trying to connect");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
898 899
    return 1;
  }
bar@mysql.com's avatar
bar@mysql.com committed
900 901 902 903 904
  /*
    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;
905 906 907 908 909
  /*
    As we're going to set SQL_MODE, it would be lost on reconnect, so we
    cannot reconnect.
  */
  sock->reconnect= 0;
910 911
  my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */",
	      compatible_mode_normal_str);
912
  if (mysql_query_with_error_report(sock, 0, buff))
913 914 915 916 917
  {
    mysql_close(sock);
    safe_exit(EX_MYSQLERR);
    return 1;
  }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
918 919 920 921 922 923 924 925 926 927 928 929 930 931
  /*
    set time_zone to UTC to allow dumping date types between servers with 
    different time zone settings
  */
  if (opt_tz_utc)
  {
    my_snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */");
    if (mysql_query_with_error_report(sock, 0, buff))
    {
      mysql_close(sock);
      safe_exit(EX_MYSQLERR);
      return 1;
    }
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
932 933 934 935 936 937 938 939 940 941
  return 0;
} /* dbConnect */


/*
** dbDisconnect -- disconnects from the host.
*/
static void dbDisconnect(char *host)
{
  if (verbose)
942
    fprintf(stderr, "-- Disconnecting from %s...\n", host ? host : "localhost");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
943 944 945 946 947 948 949 950 951 952 953 954 955
  mysql_close(sock);
} /* 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))))
  {
    ignore_errors=0;				/* Fatal error */
    safe_exit(EX_MYSQLERR);			/* Force exit */
  }
956
  mysql_real_escape_string(&mysql_connection, tmp, pos, length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
957 958 959
  fputc('\'', file);
  fputs(tmp, file);
  fputc('\'', file);
960
  check_io(file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
961 962 963 964 965 966 967 968 969
  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++)
970
    if (!my_isvar(charset_info,*str) && *str != '$')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
971 972 973 974 975
      return 1;
#endif
  return 0;
} /* test_if_special_chars */

976

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

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993
/*
  quote_name(name, buff, force)

  Quotes char string, taking into account compatible mode 

  Args

  name                 Unquoted string containing that which will be quoted
  buff                 The buffer that contains the quoted value, also returned
  force                Flag to make it ignore 'test_if_special_chars' 

  Returns

  buff                 quoted string

*/
994
static char *quote_name(const char *name, char *buff, my_bool force)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
995
{
996
  char *to= buff;
997 998
  char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';

999 1000
  if (!force && !opt_quoted && !test_if_special_chars(name))
    return (char*) name;
1001
  *to++= qtype;
1002 1003
  while (*name)
  {
1004 1005
    if (*name == qtype)
      *to++= qtype;
1006 1007
    *to++= *name++;
  }
1008 1009
  to[0]= qtype;
  to[1]= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1010 1011 1012
  return buff;
} /* quote_name */

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

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1014 1015
/*
  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
1016

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1017
  SYNOPSIS
monty@mishka.local's avatar
monty@mishka.local committed
1018 1019 1020
    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
1021 1022 1023

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

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
    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"

*/
1036 1037 1038 1039 1040 1041
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
1042 1043 1044 1045 1046 1047 1048
    if (*name == '\\')
    {
      *to++='\\';
      *to++='\\';
      *to++='\\';
    }
    else if (*name == '\'' || *name == '_'  || *name == '%')
1049 1050 1051 1052 1053 1054 1055 1056 1057
      *to++= '\\';
    *to++= *name++;
  }
  to[0]= '\'';
  to[1]= 0;
  return buff;
}


1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
/*
  Quote and print a string.
  
  SYNOPSIS
    print_quoted_xml()
    output	- output file
    str		- string to print
    len		- its length
    
  DESCRIPTION
1068
    Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
*/

static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
{
  const char *end;
  
  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;
    }
  }
1095
  check_io(xml_file);
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
}


/*
  Print xml tag with one attribute.
  
  SYNOPSIS
    print_xml_tag1()
    xml_file	- output file
    sbeg	- line beginning
    stag_atr	- tag and attribute
    sval	- value of attribute
    send	- line ending
    
  DESCRIPTION
    Print tag with one attribute to the xml_file. Format is:
      sbeg<stag_atr="sval">send
  NOTE
    sval MUST be a NULL terminated string.
    sval string will be qouted before output.
*/

static void print_xml_tag1(FILE * xml_file, const char* sbeg,
			   const char* stag_atr, const char* sval,
			   const char* send)
{
  fputs(sbeg, xml_file);
  fputs("<", xml_file);
  fputs(stag_atr, xml_file);
  fputs("\"", xml_file);
  print_quoted_xml(xml_file, sval, strlen(sval));
  fputs("\">", xml_file);
  fputs(send, xml_file);
1129
  check_io(xml_file);
1130 1131 1132
}


1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
/*
  Print xml tag with for a field that is null

  SYNOPSIS
    print_xml_null_tag()
    xml_file	- output file
    sbeg	- line beginning
    stag_atr	- tag and attribute
    sval	- value of attribute
    send	- line ending

  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,
                               const char* send)
{
  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);
  fputs(send, xml_file);
  check_io(xml_file);
}


1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
/*
  Print xml tag with many attributes.

  SYNOPSIS
    print_xml_row()
    xml_file	- output file
    row_name	- xml tag name
    tableRes	- query result
    row		- result row
    
  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,
			  MYSQL_RES *tableRes, MYSQL_ROW *row)
1186 1187 1188 1189
{
  uint i;
  MYSQL_FIELD *field;
  ulong *lengths= mysql_fetch_lengths(tableRes);
1190

1191
  fprintf(xml_file, "\t\t<%s", row_name);
1192
  check_io(xml_file);
1193 1194 1195
  mysql_field_seek(tableRes, 0);
  for (i= 0; (field= mysql_fetch_field(tableRes)); i++)
  {
1196
    if ((*row)[i])
1197
    {
monty@mishka.local's avatar
monty@mishka.local committed
1198
      fputc(' ', xml_file);
1199
      print_quoted_xml(xml_file, field->name, field->name_length);
1200 1201
      fputs("=\"", xml_file);
      print_quoted_xml(xml_file, (*row)[i], lengths[i]);
monty@mishka.local's avatar
monty@mishka.local committed
1202
      fputc('"', xml_file);
1203
      check_io(xml_file);
1204 1205 1206
    }
  }
  fputs(" />\n", xml_file);
1207
  check_io(xml_file);
1208 1209
}

1210 1211 1212 1213 1214 1215 1216 1217
/*
  dump_routines_for_db
  -- retrievs list of routines for a given db, and prints out
  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

1218 1219 1220
  RETURN
    0  Success
    1  Error
1221 1222
*/

1223
static uint dump_routines_for_db(char *db)
1224
{
1225
  char       query_buff[512];
1226 1227 1228
  const char *routine_type[]= {"FUNCTION", "PROCEDURE"};
  char       db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
  char       *routine_name;
1229
  int        i;
1230
  FILE       *sql_file= md_result_file;
1231
  MYSQL_RES  *routine_res, *routine_list_res;
1232
  MYSQL_ROW  row, routine_list_row;
1233
  DBUG_ENTER("dump_routines_for_db");
1234
  DBUG_PRINT("enter", ("db: '%s'", db));
1235 1236 1237 1238 1239 1240

  mysql_real_escape_string(sock, db_name_buff, db, strlen(db));

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

  /*
1243 1244
    not using "mysql_query_with_error_report" because we may have not
    enough privileges to lock mysql.proc.
1245
  */
1246
  if (lock_tables)
1247 1248
    mysql_query(sock, "LOCK TABLES mysql.proc READ");

1249
  fprintf(sql_file, "DELIMITER ;;\n");
1250 1251

  /* 0, retrieve and dump functions, 1, procedures */
1252
  for (i= 0; i <= 1; i++)
1253 1254 1255
  {
    my_snprintf(query_buff, sizeof(query_buff),
                "SHOW %s STATUS WHERE Db = '%s'",
1256
                routine_type[i], db_name_buff);
1257

1258
    if (mysql_query_with_error_report(sock, &routine_list_res, query_buff))
1259 1260 1261 1262 1263
      DBUG_RETURN(1);

    if (mysql_num_rows(routine_list_res))
    {

1264
      while ((routine_list_row= mysql_fetch_row(routine_list_res)))
1265
      {
1266 1267
        DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i],
                            name_buff));
1268
        routine_name= quote_name(routine_list_row[1], name_buff, 0);
1269
        my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s",
1270
                    routine_type[i], routine_name);
1271 1272 1273 1274

        if (mysql_query_with_error_report(sock, &routine_res, query_buff))
          DBUG_RETURN(1);

1275
        while ((row= mysql_fetch_row(routine_res)))
1276 1277
        {
          /*
1278 1279
            if the user has EXECUTE privilege he see routine names, but NOT the
            routine body of other routines that are not the creator of!
1280 1281
          */
          DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d",
1282
                             routine_name, row[2], strlen(row[2])));
1283 1284 1285
          if (strlen(row[2]))
          {
            if (opt_drop)
1286
              fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n",
1287
                      routine_type[i], routine_name);
1288
            /*
1289 1290
              we need to change sql_mode only for the CREATE
              PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name
1291
            */;
1292
            fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n",
1293
                    row[1] /* sql_mode */);
1294 1295 1296 1297
            fprintf(sql_file, "/*!50003 %s */;;\n", row[2]);
            fprintf(sql_file,
                    "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/"
                    ";;\n");
1298 1299 1300 1301 1302 1303 1304
          }
        } /* end of routine printing */
      } /* end of list of routines */
      mysql_free_result(routine_res);
    }
    mysql_free_result(routine_list_res);
  } /* end of for i (0 .. 1)  */
1305 1306
  /* set the delimiter back to ';' */
  fprintf(sql_file, "DELIMITER ;\n");
1307

1308 1309
  if (lock_tables)
    mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
1310 1311
  DBUG_RETURN(0);
}
1312

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1313
/*
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1314 1315 1316 1317 1318 1319 1320 1321 1322
  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
    table_type  - table type ie "InnoDB"
    ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1323 1324 1325

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

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1328 1329
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
1330
{
monty@mysql.com's avatar
monty@mysql.com committed
1331
  my_bool    init=0, delayed, write_data, complete_insert;
1332
  my_ulonglong num_fields;
1333
  char	     *result_table, *opt_quoted_table;
1334
  const char *insert_option;
1335
  char	     name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
1336
  char	     table_buff2[NAME_LEN*2+3], query_buff[512];
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
1337
  FILE       *sql_file = md_result_file;
1338
  int        len;
1339 1340 1341
  MYSQL_RES  *result;
  MYSQL_ROW  row;

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

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

monty@mysql.com's avatar
monty@mysql.com committed
1347 1348 1349 1350
  delayed= opt_delayed;
  if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
  {
    delayed= 0;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1351 1352
    if (verbose)
      fprintf(stderr,
monty@mysql.com's avatar
monty@mysql.com committed
1353 1354 1355
              "-- Warning: Unable to use delayed inserts for table '%s' "
              "because it's of type %s\n", table, table_type);
  }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1356

monty@mysql.com's avatar
monty@mysql.com committed
1357 1358
  complete_insert= 0;
  if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1359
  {
monty@mysql.com's avatar
monty@mysql.com committed
1360
    complete_insert= opt_complete_insert;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1361 1362 1363 1364
    if (!insert_pat_inited)
      insert_pat_inited= init_dynamic_string(&insert_pat, "", 1024, 1024);
    else
      dynstr_set(&insert_pat, "");
1365 1366
  }

monty@mysql.com's avatar
monty@mysql.com committed
1367 1368
  insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
                  delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1369 1370

  if (verbose)
1371
    fprintf(stderr, "-- Retrieving table structure for table %s...\n", table);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1372

1373 1374 1375
  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
1376
  if (!create_options)
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1377 1378
    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
1379

1380 1381
  result_table=     quote_name(table, table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);
1382 1383

  if (opt_order_by_primary)
monty@mishka.local's avatar
monty@mishka.local committed
1384
    order_by = primary_key_fields(result_table);
1385

1386
  if (!opt_xml && !mysql_query_with_error_report(sock, 0, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1387
  {
1388 1389
    /* using SHOW CREATE statement */
    if (!tFlag)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1390
    {
1391 1392
      /* Make an sql-file, if path was given iow. option -T was given */
      char buff[20+FN_REFLEN];
1393
      MYSQL_FIELD *field;
1394

1395
      my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
1396
      if (mysql_query_with_error_report(sock, 0, buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1397
      {
1398 1399
        safe_exit(EX_MYSQLERR);
        DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1400 1401
      }

1402 1403 1404
      if (path)
      {
        char filename[FN_REFLEN], tmp_path[FN_REFLEN];
1405
        convert_dirname(tmp_path,path,NullS);
1406
        sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
1407
				 O_WRONLY, MYF(MY_WME));
1408 1409
        if (!sql_file)			/* If file couldn't be opened */
        {
1410 1411
	  safe_exit(EX_MYSQLERR);
	  DBUG_RETURN(0);
1412
        }
1413
        write_header(sql_file, db);
1414
      }
1415
      if (!opt_xml && opt_comments)
1416
      {
monty@mysql.com's avatar
monty@mysql.com committed
1417
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1418
		result_table);
1419 1420
	check_io(sql_file);
      }
1421
      if (opt_drop)
1422
      {
1423
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
1424 1425
	check_io(sql_file);
      }
1426

1427 1428
      result= mysql_store_result(sock);
      field= mysql_fetch_field_direct(result, 0);
1429 1430 1431
      if (strcmp(field->name, "View") == 0)
      {
        if (verbose)
1432 1433
          fprintf(stderr, "-- It's a view, create dummy table for view\n");

1434 1435 1436 1437 1438 1439
        mysql_free_result(result);

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

1441 1442
          The properties of each column, aside from the data type, are not
          preserved in this temporary table, because they are not necessary.
1443

1444 1445 1446
          This will not be necessary once we can determine dependencies
          between views and can simply dump them in the appropriate order.
        */
1447
        my_snprintf(query_buff, sizeof(query_buff),
1448
                    "SHOW FIELDS FROM %s", result_table);
1449 1450 1451 1452 1453 1454
        if (mysql_query_with_error_report(sock, 0, query_buff))
        {
          safe_exit(EX_MYSQLERR);
          DBUG_RETURN(0);
        }

1455
        if ((result= mysql_store_result(sock)))
1456
        {
1457 1458 1459 1460 1461 1462
          if (mysql_num_rows(result))
          {
            if (opt_drop)
            {
              fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
                      opt_quoted_table);
1463 1464
              fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n",
                      opt_quoted_table);
1465 1466
              check_io(sql_file);
            }
1467

1468 1469 1470 1471 1472 1473 1474 1475
            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);

1476 1477
            fprintf(sql_file, "  %s %s", quote_name(row[0], name_buff, 0),
                    row[1]);
1478 1479 1480 1481 1482 1483 1484 1485 1486 1487

            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);
          }
1488
        }
1489 1490
        mysql_free_result(result);

1491 1492 1493
        was_views= 1;
        DBUG_RETURN(0);
      }
1494 1495

      row= mysql_fetch_row(result);
1496
      fprintf(sql_file, "%s;\n", row[1]);
1497
      check_io(sql_file);
1498
      mysql_free_result(result);
1499
    }
1500
    my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1501
		result_table);
1502
    if (mysql_query_with_error_report(sock, &result, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1503
    {
1504 1505
      if (path)
	my_fclose(sql_file, MYF(MY_WME));
1506 1507
      safe_exit(EX_MYSQLERR);
      DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1508
    }
1509

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1510
    /*
monty@mysql.com's avatar
monty@mysql.com committed
1511 1512 1513 1514
      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
1515
    */
monty@mysql.com's avatar
monty@mysql.com committed
1516
    if (write_data)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1517
    {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1518 1519 1520 1521
      dynstr_append_mem(&insert_pat, "INSERT ", 7);
      dynstr_append(&insert_pat, insert_option);
      dynstr_append_mem(&insert_pat, "INTO ", 5);
      dynstr_append(&insert_pat, opt_quoted_table);
monty@mysql.com's avatar
monty@mysql.com committed
1522
      if (complete_insert)
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1523 1524 1525 1526 1527 1528 1529 1530 1531
      {
        dynstr_append_mem(&insert_pat, " (", 2);
      }
      else
      {
        dynstr_append_mem(&insert_pat, " VALUES ", 8);
        if (!extended_insert)
          dynstr_append_mem(&insert_pat, "(", 1);
      }
1532 1533
    }

1534
    while ((row= mysql_fetch_row(result)))
1535
    {
monty@mysql.com's avatar
monty@mysql.com committed
1536
      if (complete_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1537
      {
monty@mysql.com's avatar
monty@mysql.com committed
1538 1539
        if (init)
        {
1540
          dynstr_append_mem(&insert_pat, ", ", 2);
monty@mysql.com's avatar
monty@mysql.com committed
1541 1542
        }
        init=1;
1543 1544
        dynstr_append(&insert_pat,
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
monty@mysql.com's avatar
monty@mysql.com committed
1545
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1546
    }
1547 1548
    num_fields= mysql_num_rows(result);
    mysql_free_result(result);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1549
  }
1550
  else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1551
  {
monty@mishka.local's avatar
monty@mishka.local committed
1552 1553 1554 1555
    if (verbose)
      fprintf(stderr,
              "%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
              my_progname, mysql_error(sock));
1556

1557
    my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1558
		result_table);
1559
    if (mysql_query_with_error_report(sock, &result, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1560 1561 1562 1563 1564
    {
      safe_exit(EX_MYSQLERR);
      DBUG_RETURN(0);
    }

1565 1566
    /* Make an sql-file, if path was given iow. option -T was given */
    if (!tFlag)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1567
    {
1568
      if (path)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1569
      {
1570
        char filename[FN_REFLEN], tmp_path[FN_REFLEN];
1571
        convert_dirname(tmp_path,path,NullS);
1572 1573 1574 1575
        sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
				 O_WRONLY, MYF(MY_WME));
        if (!sql_file)			/* If file couldn't be opened */
        {
1576 1577
	  safe_exit(EX_MYSQLERR);
	  DBUG_RETURN(0);
1578
        }
1579
        write_header(sql_file, db);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1580
      }
1581
      if (!opt_xml && opt_comments)
1582 1583
	fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
		result_table);
1584
      if (opt_drop)
monty@mishka.local's avatar
monty@mishka.local committed
1585
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1586 1587 1588
      if (!opt_xml)
	fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
      else
1589
        print_xml_tag1(sql_file, "\t", "table_structure name=", table, "\n");
1590
      check_io(sql_file);
1591
    }
1592

monty@mysql.com's avatar
monty@mysql.com committed
1593
    if (write_data)
1594
    {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
      dynstr_append_mem(&insert_pat, "INSERT ", 7);
      dynstr_append(&insert_pat, insert_option);
      dynstr_append_mem(&insert_pat, "INTO ", 5);
      dynstr_append(&insert_pat, result_table);
      if (opt_complete_insert)
        dynstr_append_mem(&insert_pat, " (", 2);
      else
      {
        dynstr_append_mem(&insert_pat, " VALUES ", 8);
        if (!extended_insert)
          dynstr_append_mem(&insert_pat, "(", 1);
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1607
    }
1608

1609
    while ((row= mysql_fetch_row(result)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1610
    {
1611
      ulong *lengths= mysql_fetch_lengths(result);
1612
      if (init)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1613
      {
1614
        if (!opt_xml && !tFlag)
1615
	{
1616
	  fputs(",\n",sql_file);
1617 1618
	  check_io(sql_file);
	}
monty@mysql.com's avatar
monty@mysql.com committed
1619
        if (complete_insert)
1620
          dynstr_append_mem(&insert_pat, ", ", 2);
1621 1622
      }
      init=1;
monty@mysql.com's avatar
monty@mysql.com committed
1623
      if (opt_complete_insert)
1624 1625
        dynstr_append(&insert_pat,
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1626 1627
      if (!tFlag)
      {
1628 1629
	if (opt_xml)
	{
1630
	  print_xml_row(sql_file, "field", result, &row);
1631 1632
	  continue;
	}
1633

1634
        if (opt_keywords)
1635
	  fprintf(sql_file, "  %s.%s %s", result_table,
1636 1637
		  quote_name(row[SHOW_FIELDNAME],name_buff, 0),
		  row[SHOW_TYPE]);
1638
        else
1639
	  fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
1640 1641
						  name_buff, 0),
		  row[SHOW_TYPE]);
1642 1643
        if (row[SHOW_DEFAULT])
        {
1644
	  fputs(" DEFAULT ", sql_file);
1645
	  unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1646 1647
        }
        if (!row[SHOW_NULL][0])
1648
	  fputs(" NOT NULL", sql_file);
1649
        if (row[SHOW_EXTRA][0])
1650
	  fprintf(sql_file, " %s",row[SHOW_EXTRA]);
1651
	check_io(sql_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1652 1653
      }
    }
1654 1655
    num_fields= mysql_num_rows(result);
    mysql_free_result(result);
1656
    if (!tFlag)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1657
    {
1658 1659 1660
      /* Make an sql-file, if path was given iow. option -T was given */
      char buff[20+FN_REFLEN];
      uint keynr,primary_key;
1661
      my_snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1662
      if (mysql_query_with_error_report(sock, &result, buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1663
      {
1664 1665 1666 1667 1668 1669 1670 1671
        if (mysql_errno(sock) == ER_WRONG_OBJECT)
        {
          /* 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",
		my_progname, result_table, mysql_error(sock));
1672
        if (path)
1673
	  my_fclose(sql_file, MYF(MY_WME));
1674 1675
        safe_exit(EX_MYSQLERR);
        DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1676
      }
1677 1678 1679 1680

      /* Find first which key is primary key */
      keynr=0;
      primary_key=INT_MAX;
1681
      while ((row= mysql_fetch_row(result)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1682
      {
1683 1684
        if (atoi(row[3]) == 1)
        {
1685 1686 1687 1688 1689 1690 1691 1692 1693 1694
	  keynr++;
#ifdef FORCE_PRIMARY_KEY
	  if (atoi(row[1]) == 0 && primary_key == INT_MAX)
	    primary_key=keynr;
#endif
	  if (!strcmp(row[2],"PRIMARY"))
	  {
	    primary_key=keynr;
	    break;
	  }
1695
        }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1696
      }
1697
      mysql_data_seek(result,0);
1698
      keynr=0;
1699
      while ((row= mysql_fetch_row(result)))
1700
      {
1701 1702
	if (opt_xml)
	{
1703
	  print_xml_row(sql_file, "key", result, &row);
1704 1705
	  continue;
	}
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1706

1707 1708
        if (atoi(row[3]) == 1)
        {
1709 1710 1711 1712
	  if (keynr++)
	    putc(')', sql_file);
	  if (atoi(row[1]))       /* Test if duplicate key */
	    /* Duplicate allowed */
1713
	    fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff,0));
1714 1715 1716
	  else if (keynr == primary_key)
	    fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
	  else
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1717 1718
	    fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff,
							    0));
1719 1720
        }
        else
1721
	  putc(',', sql_file);
1722
        fputs(quote_name(row[4], name_buff, 0), sql_file);
1723
        if (row[7])
1724
	  fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
1725
	check_io(sql_file);
1726
      }
1727 1728 1729 1730 1731
      if (!opt_xml)
      {
	if (keynr)
	  putc(')', sql_file);
	fputs("\n)",sql_file);
1732
	check_io(sql_file);
1733
      }
1734 1735 1736

      /* Get MySQL specific create options */
      if (create_options)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1737
      {
1738
	char show_name_buff[NAME_LEN*2+2+24];
1739 1740 1741 1742 1743

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

1744
        if (mysql_query_with_error_report(sock, &result, buff))
1745
        {
1746 1747 1748 1749
	  if (mysql_errno(sock) != ER_PARSE_ERROR)
	  {					/* If old MySQL version */
	    if (verbose)
	      fprintf(stderr,
1750 1751
		      "-- Warning: Couldn't get status information for table %s (%s)\n",
		      result_table,mysql_error(sock));
1752
	  }
1753
        }
1754
        else if (!(row= mysql_fetch_row(result)))
1755
        {
1756
	  fprintf(stderr,
1757 1758
		  "Error: Couldn't read status information for table %s (%s)\n",
		  result_table,mysql_error(sock));
1759 1760 1761
        }
        else
        {
1762
	  if (opt_xml)
1763
	    print_xml_row(sql_file, "options", result, &row);
1764 1765 1766
	  else
	  {
	    fputs("/*!",sql_file);
1767 1768 1769
	    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);
1770
	    fputs(" */",sql_file);
1771
	    check_io(sql_file);
1772
	  }
1773
        }
1774
        mysql_free_result(result);		/* Is always safe to free */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1775
      }
1776
continue_xml:
1777 1778 1779 1780
      if (!opt_xml)
	fputs(";\n", sql_file);
      else
	fputs("\t</table_structure>\n", sql_file);
1781
      check_io(sql_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1782 1783
    }
  }
monty@mysql.com's avatar
monty@mysql.com committed
1784
  if (opt_complete_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1785
  {
1786
    dynstr_append_mem(&insert_pat, ") VALUES ", 9);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1787
    if (!extended_insert)
1788
      dynstr_append_mem(&insert_pat, "(", 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1789
  }
1790
  if (sql_file != md_result_file)
1791 1792 1793
  {
    fputs("\n", sql_file);
    write_footer(sql_file);
1794
    my_fclose(sql_file, MYF(MY_WME));
1795
  }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1796
  DBUG_RETURN(num_fields);
1797
} /* get_table_structure */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1798 1799


1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812
/*

  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

*/

static void dump_triggers_for_table (char *table, char *db)
{
  char	     *result_table;
1813
  char	     name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
1814
  char       query_buff[512];
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1815
  uint old_opt_compatible_mode=opt_compatible_mode;
1816
  FILE       *sql_file = md_result_file;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1817 1818 1819
  MYSQL_RES  *result;
  MYSQL_ROW  row;

1820 1821
  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
1822 1823 1824

  /* Do not use ANSI_QUOTES on triggers in dump */
  opt_compatible_mode&= ~MASK_ANSI_QUOTES;
1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
  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));

  if (mysql_query_with_error_report(sock, &result, query_buff))
  {
    if (path)
      my_fclose(sql_file, MYF(MY_WME));
    safe_exit(EX_MYSQLERR);
    DBUG_VOID_RETURN;
  }
  if (mysql_num_rows(result))
    fprintf(sql_file, "\n/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n\
1840
DELIMITER ;;\n");
1841
  while ((row= mysql_fetch_row(result)))
1842
  {
1843
    fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n\
1844
/*!50003 CREATE TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n\n",
1845 1846 1847 1848 1849
            row[6], /* sql_mode */
            quote_name(row[0], name_buff, 0), /* Trigger */
            row[4], /* Timing */
            row[1], /* Event */
            result_table,
1850
	    (strchr(" \t\n\r", *(row[3]))) ? "" : " ",
1851 1852 1853 1854
            row[3] /* Statement */);
  }
  if (mysql_num_rows(result))
    fprintf(sql_file,
1855 1856
            "DELIMITER ;\n"
            "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n");
1857
  mysql_free_result(result);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1858 1859 1860 1861 1862
  /*
    make sure to set back opt_compatible mode to 
    original value
  */
  opt_compatible_mode=old_opt_compatible_mode;
1863 1864 1865
  DBUG_VOID_RETURN;
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1866 1867 1868 1869 1870
static char *add_load_option(char *ptr,const char *object,
			     const char *statement)
{
  if (object)
  {
1871 1872 1873 1874 1875 1876 1877 1878 1879 1880
    /* Don't escape hex constants */
    if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
      ptr= strxmov(ptr," ",statement," ",object,NullS);
    else
    {
      /* char constant; escape */
      ptr= strxmov(ptr," ",statement," '",NullS);
      ptr= field_escape(ptr,object,(uint) strlen(object));
      *ptr++= '\'';
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1881 1882 1883 1884 1885 1886
  }
  return ptr;
} /* add_load_option */


/*
1887 1888 1889 1890
  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
1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916
*/

static char *field_escape(char *to,const char *from,uint length)
{
  const char *end;
  uint end_backslashes=0;

  for (end= from+length; from != end; from++)
  {
    *to++= *from;
    if (*from == '\\')
      end_backslashes^=1;    /* find odd number of backslashes */
    else
    {
      if (*from == '\'' && !end_backslashes)
	*to++= *from;      /* We want a duplicate of "'" for MySQL */
      end_backslashes=0;
    }
  }
  /* Add missing backslashes if user has specified odd number of backs.*/
  if (end_backslashes)
    *to++= '\\';
  return to;
} /* field_escape */


1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928
static char *alloc_query_str(ulong size)
{
  char *query;

  if (!(query= (char*) my_malloc(size, MYF(MY_WME))))
  {
    ignore_errors= 0;   			/* Fatal error */
    safe_exit(EX_MYSQLERR);			/* Force exit */
  }
  return query;
}

1929

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1930
/*
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942

 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
1943
*/
1944

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1945
static void dump_table(char *table, char *db)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1946
{
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1947
  char ignore_flag;
1948
  char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3];
monty@mysql.com's avatar
monty@mysql.com committed
1949
  char table_type[NAME_LEN];
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1950
  char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
1951
  char *query= query_buf;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1952 1953 1954
  int error= 0;
  ulong		rownr, row_break, total_length, init_length;
  uint num_fields;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1955
  MYSQL_RES	*res;
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1956 1957
  MYSQL_FIELD	*field;
  MYSQL_ROW	row;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1958 1959 1960 1961 1962 1963
  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
1964
  num_fields= get_table_structure(table, db, table_type, &ignore_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1965

1966 1967 1968 1969 1970 1971 1972
  /* Check --no-data flag */
  if (dFlag)
  {
    if (verbose)
      fprintf(stderr,
              "-- Skipping dump data for table '%s', --no-data was used\n",
	      table);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1973
    DBUG_VOID_RETURN;
1974 1975
  }

monty@mysql.com's avatar
monty@mysql.com committed
1976 1977 1978
  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
1979 1980 1981 1982 1983 1984 1985 1986
  /*
    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)
  {
    if (verbose)
      fprintf(stderr,
monty@mysql.com's avatar
monty@mysql.com committed
1987
	      "-- Warning: Skipping data for table '%s' because it's of type %s\n",
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1988 1989 1990
	      table, table_type);
    DBUG_VOID_RETURN;
  }
1991
  /* Check that there are any fields in the table */
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1992
  if (num_fields == 0)
1993 1994 1995 1996 1997
  {
    if (verbose)
      fprintf(stderr,
	      "-- Skipping dump data for table '%s', it has no fields\n",
	      table);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1998
    DBUG_VOID_RETURN;
1999 2000
  }

2001 2002
  result_table= quote_name(table,table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);
2003 2004 2005

  if (verbose)
    fprintf(stderr, "-- Sending SELECT query...\n");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2006 2007 2008
  if (path)
  {
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
2009
    convert_dirname(tmp_path,path,NullS);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2010 2011 2012 2013 2014
    my_load_path(tmp_path, tmp_path, NULL);
    fn_format(filename, table, tmp_path, ".txt", 4);
    my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if
				    filename wasn't deleted */
    to_unix_path(filename);
2015 2016 2017
    my_snprintf(query, QUERY_LENGTH, 
		"SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
		filename);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028
    end= strend(query);

    if (fields_terminated || enclosed || opt_enclosed || escaped)
      end= strmov(end, " FIELDS");
    end= add_load_option(end, fields_terminated, " TERMINATED BY");
    end= add_load_option(end, enclosed, " ENCLOSED BY");
    end= add_load_option(end, opt_enclosed, " OPTIONALLY ENCLOSED BY");
    end= add_load_option(end, escaped, " ESCAPED BY");
    end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
    *end= '\0';

2029
    my_snprintf(buff, sizeof(buff), " FROM %s", result_table);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2030
    end= strmov(end,buff);
2031
    if (where || order_by)
2032
    {
2033 2034 2035 2036 2037 2038 2039 2040 2041
      query = alloc_query_str((ulong) ((end - query) + 1 +
                             (where ? strlen(where) + 7 : 0) +
                             (order_by ? strlen(order_by) + 10 : 0)));
      end = strmov(query, query_buf);

      if (where)
        end = strxmov(end, " WHERE ", where, NullS);
      if (order_by)
        end = strxmov(end, " ORDER BY ", order_by, NullS);
2042 2043
    }
    if (mysql_real_query(sock, query, (uint) (end - query)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2044
    {
2045
      DB_error(sock, "when executing 'SELECT INTO OUTFILE'");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2046
      DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2047 2048 2049 2050
    }
  }
  else
  {
2051
    if (!opt_xml && opt_comments)
2052
    {
2053 2054
      fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
	      result_table);
2055 2056
      check_io(md_result_file);
    }
2057 2058 2059
    my_snprintf(query, QUERY_LENGTH,
		"SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
		result_table);
2060
    if (where || order_by)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2061
    {
2062 2063 2064 2065 2066 2067
      query = alloc_query_str((ulong) (strlen(query) + 1 +
                             (where ? strlen(where) + 7 : 0) +
                             (order_by ? strlen(order_by) + 10 : 0)));
      end = strmov(query, query_buf);

      if (where)
2068
      {
2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083
        if (!opt_xml && opt_comments)
        {
          fprintf(md_result_file, "-- WHERE:  %s\n", where);
          check_io(md_result_file);
        }
        end = strxmov(end, " WHERE ", where, NullS);
      }
      if (order_by)
      {
        if (!opt_xml && opt_comments)
        {
          fprintf(md_result_file, "-- ORDER BY:  %s\n", order_by);
          check_io(md_result_file);
        }
        end = strxmov(end, " ORDER BY ", order_by, NullS);
2084
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2085
    }
2086
    if (!opt_xml && !opt_compact)
2087
    {
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2088
      fputs("\n", md_result_file);
2089 2090
      check_io(md_result_file);
    }
2091
    if (mysql_query_with_error_report(sock, 0, query))
2092
      DB_error(sock, "when retrieving data from server");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2093 2094 2095 2096 2097
    if (quick)
      res=mysql_use_result(sock);
    else
      res=mysql_store_result(sock);
    if (!res)
2098
      DB_error(sock, "when retrieving data from server");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2099
    if (verbose)
2100
      fprintf(stderr, "-- Retrieving rows...\n");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2101
    if (mysql_num_fields(res) != num_fields)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2102
    {
2103 2104
      fprintf(stderr,"%s: Error in field count for table: %s !  Aborting.\n",
	      my_progname, result_table);
2105 2106
      error= EX_CONSCHECK;
      goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2107 2108
    }

jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2109
    if (opt_disable_keys)
2110
    {
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2111
      fprintf(md_result_file, "\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2112
	      opt_quoted_table);
2113 2114
      check_io(md_result_file);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2115
    if (opt_lock)
2116
    {
2117
      fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
2118 2119
      check_io(md_result_file);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2120

2121
    total_length= opt_net_buffer_length;		/* Force row break */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2122 2123
    row_break=0;
    rownr=0;
2124
    init_length=(uint) insert_pat.length+4;
2125
    if (opt_xml)
2126
      print_xml_tag1(md_result_file, "\t", "table_data name=", table, "\n");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2127

2128
    if (opt_autocommit)
2129
    {
2130
      fprintf(md_result_file, "set autocommit=0;\n");
2131 2132
      check_io(md_result_file);
    }
2133

2134
    while ((row= mysql_fetch_row(res)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2135 2136
    {
      uint i;
2137
      ulong *lengths= mysql_fetch_lengths(res);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2138
      rownr++;
2139
      if (!extended_insert && !opt_xml)
2140
      {
2141
	fputs(insert_pat.str,md_result_file);
2142 2143
	check_io(md_result_file);
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2144 2145
      mysql_field_seek(res,0);

jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2146
      if (opt_xml)
2147
      {
2148
        fputs("\t<row>\n", md_result_file);
2149 2150
	check_io(md_result_file);
      }
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2151

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2152 2153
      for (i = 0; i < mysql_num_fields(res); i++)
      {
2154
        int is_blob;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2155 2156
	if (!(field = mysql_fetch_field(res)))
	{
2157 2158 2159
	  my_snprintf(query, QUERY_LENGTH,
		      "%s: Not enough fields from table %s! Aborting.\n",
		      my_progname, result_table);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2160
	  fputs(query,stderr);
2161 2162
	  error= EX_CONSCHECK;
	  goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2163
	}
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2164

2165 2166 2167
	/*
	   63 is my_charset_bin. If charsetnr is not 63,
	   we have not a BLOB but a TEXT column. 
bar@mysql.com's avatar
bar@mysql.com committed
2168
	   we'll dump in hex only BLOB columns.
2169 2170
	*/
        is_blob= (opt_hex_blob && field->charsetnr == 63 &&
2171 2172
                  (field->type == MYSQL_TYPE_BIT ||
                   field->type == MYSQL_TYPE_STRING ||
2173 2174 2175 2176 2177 2178
                   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;
2179
	if (extended_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
	{
	  ulong length = lengths[i];
	  if (i == 0)
	    dynstr_set(&extended_row,"(");
	  else
	    dynstr_append(&extended_row,",");

	  if (row[i])
	  {
	    if (length)
	    {
2191
	      if (!IS_NUM_FIELD(field))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2192
	      {
bar@mysql.com's avatar
bar@mysql.com committed
2193 2194 2195 2196 2197 2198 2199
	        /*
	          "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.
	        */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2200 2201 2202
		if (dynstr_realloc(&extended_row,length * 2+2))
		{
		  fputs("Aborting dump (out of memory)",stderr);
2203 2204
		  error= EX_EOM;
		  goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2205
		}
2206 2207 2208
                if (opt_hex_blob && is_blob)
                {
                  dynstr_append(&extended_row, "0x");
bar@mysql.com's avatar
bar@mysql.com committed
2209 2210 2211 2212
                  extended_row.length+= mysql_hex_string(extended_row.str + 
                                                         extended_row.length,
                                                         row[i], length);
                  extended_row.str[extended_row.length]= '\0';
2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223
                }
                else
                {
                  dynstr_append(&extended_row,"'");
                  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';
                  dynstr_append(&extended_row,"'");
                }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2224 2225
	      }
	      else
2226
	      {
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
2227
		/* change any strings ("inf", "-inf", "nan") into NULL */
2228
		char *ptr = row[i];
monty@mysql.com's avatar
monty@mysql.com committed
2229 2230
		if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
		    my_isalpha(charset_info, ptr[1])))
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
2231 2232 2233 2234 2235 2236
		  dynstr_append(&extended_row, "NULL");
		else
		{
		  if (field->type == FIELD_TYPE_DECIMAL)
		  {
		    /* add " signs around */
monty@mishka.local's avatar
monty@mishka.local committed
2237
		    dynstr_append(&extended_row, "'");
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
2238
		    dynstr_append(&extended_row, ptr);
monty@mishka.local's avatar
monty@mishka.local committed
2239
		    dynstr_append(&extended_row, "'");
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
2240 2241 2242 2243
		  }
		  else
		    dynstr_append(&extended_row, ptr);
		}
2244
	      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2245 2246
	    }
	    else
monty@mishka.local's avatar
monty@mishka.local committed
2247
	      dynstr_append(&extended_row,"''");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2248 2249 2250 2251
	  }
	  else if (dynstr_append(&extended_row,"NULL"))
	  {
	    fputs("Aborting dump (out of memory)",stderr);
2252 2253
	    error= EX_EOM;
	    goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2254 2255 2256 2257
	  }
	}
	else
	{
2258
	  if (i && !opt_xml)
2259
	  {
2260
	    fputc(',', md_result_file);
2261 2262
	    check_io(md_result_file);
	  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2263 2264
	  if (row[i])
	  {
2265
	    if (!IS_NUM_FIELD(field))
2266
	    {
2267
	      if (opt_xml)
2268
	      {
2269 2270
	        print_xml_tag1(md_result_file, "\t\t", "field name=",
			      field->name, "");
2271 2272 2273
		print_quoted_xml(md_result_file, row[i], lengths[i]);
		fputs("</field>\n", md_result_file);
	      }
2274
	      else if (opt_hex_blob && is_blob)
monty@mysql.com's avatar
monty@mysql.com committed
2275 2276
              {
                /* sakaik got the idea to to provide blob's in hex notation. */
2277
                char *ptr= row[i], *end= ptr+ lengths[i];
2278
                fputs("0x", md_result_file);
monty@mysql.com's avatar
monty@mysql.com committed
2279
                for (; ptr < end ; ptr++)
2280
		  fprintf(md_result_file, "%02X", *((uchar *)ptr));
2281 2282 2283
              }
              else
                unescape(md_result_file, row[i], lengths[i]);
2284
	    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2285
	    else
2286
	    {
ram@gw.mysql.r18.ru's avatar
ram@gw.mysql.r18.ru committed
2287
	      /* change any strings ("inf", "-inf", "nan") into NULL */
2288
	      char *ptr = row[i];
2289
	      if (opt_xml)
2290
	      {
2291 2292
	        print_xml_tag1(md_result_file, "\t\t", "field name=",
			       field->name, "");
2293 2294 2295 2296
		fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
		      md_result_file);
		fputs("</field>\n", md_result_file);
	      }
monty@mysql.com's avatar
monty@mysql.com committed
2297 2298 2299 2300
	      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)
monty@mysql.com's avatar
monty@mysql.com committed
2301 2302
	      {
		/* add " signs around */
monty@mishka.local's avatar
monty@mishka.local committed
2303
		fputc('\'', md_result_file);
monty@mysql.com's avatar
monty@mysql.com committed
2304
		fputs(ptr, md_result_file);
monty@mishka.local's avatar
monty@mishka.local committed
2305
		fputc('\'', md_result_file);
monty@mysql.com's avatar
monty@mysql.com committed
2306
	      }
2307
	      else
monty@mysql.com's avatar
monty@mysql.com committed
2308
		fputs(ptr, md_result_file);
2309
	    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2310
	  }
2311
	  else
2312 2313 2314 2315 2316 2317 2318 2319
          {
            /* 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
2320
          check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2321 2322 2323
	}
      }

jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2324
      if (opt_xml)
2325
      {
2326
        fputs("\t</row>\n", md_result_file);
2327 2328
	check_io(md_result_file);
      }
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2329

2330
      if (extended_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2331 2332 2333 2334
      {
	ulong row_length;
	dynstr_append(&extended_row,")");
        row_length = 2 + extended_row.length;
2335
        if (total_length + row_length < opt_net_buffer_length)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2336 2337
        {
	  total_length += row_length;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2338 2339
	  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
2340 2341 2342
	}
        else
        {
2343
	  if (row_break)
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2344
	    fputs(";\n", md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2345
	  row_break=1;				/* This is first row */
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2346

2347
          fputs(insert_pat.str,md_result_file);
2348
          fputs(extended_row.str,md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2349 2350
	  total_length = row_length+init_length;
        }
2351
	check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2352
      }
2353
      else if (!opt_xml)
2354
      {
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2355
	fputs(");\n", md_result_file);
2356 2357
	check_io(md_result_file);
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2358
    }
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2359

2360
    /* XML - close table tag and supress regular output */
2361
    if (opt_xml)
2362
	fputs("\t</table_data>\n", md_result_file);
2363
    else if (extended_insert && row_break)
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2364 2365
      fputs(";\n", md_result_file);		/* If not empty table */
    fflush(md_result_file);
2366
    check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2367 2368
    if (mysql_errno(sock))
    {
2369 2370 2371 2372 2373 2374 2375
      my_snprintf(query, QUERY_LENGTH,
		  "%s: Error %d: %s when dumping table %s at row: %ld\n",
		  my_progname,
		  mysql_errno(sock),
		  mysql_error(sock),
		  result_table,
		  rownr);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2376
      fputs(query,stderr);
2377 2378
      error= EX_CONSCHECK;
      goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2379 2380
    }
    if (opt_lock)
2381
    {
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2382
      fputs("UNLOCK TABLES;\n", md_result_file);
2383 2384
      check_io(md_result_file);
    }
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2385
    if (opt_disable_keys)
2386
    {
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2387
      fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2388
	      opt_quoted_table);
2389 2390
      check_io(md_result_file);
    }
2391
    if (opt_autocommit)
2392
    {
2393
      fprintf(md_result_file, "commit;\n");
2394 2395
      check_io(md_result_file);
    }
2396
    mysql_free_result(res);
2397 2398
    if (query != query_buf)
      my_free(query, MYF(MY_ALLOW_ZERO_PTR));
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2399 2400
  }
  DBUG_VOID_RETURN;
2401 2402 2403 2404 2405

err:
  if (query != query_buf)
    my_free(query, MYF(MY_ALLOW_ZERO_PTR));
  safe_exit(error);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2406
  DBUG_VOID_RETURN;
2407
} /* dump_table */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421


static char *getTableName(int reset)
{
  static MYSQL_RES *res = NULL;
  MYSQL_ROW    row;

  if (!res)
  {
    if (!(res = mysql_list_tables(sock,NullS)))
      return(NULL);
  }
  if ((row = mysql_fetch_row(res)))
    return((char*) row[0]);
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
2422

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439
  if (reset)
    mysql_data_seek(res,0);      /* We want to read again */
  else
  {
    mysql_free_result(res);
    res = NULL;
  }
  return(NULL);
} /* getTableName */


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

2440
  if (mysql_query_with_error_report(sock, &tableres, "SHOW DATABASES"))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2441 2442 2443 2444 2445 2446
    return 1;
  while ((row = mysql_fetch_row(tableres)))
  {
    if (dump_all_tables_in_db(row[0]))
      result=1;
  }
2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461
  if (was_views)
  {
    if (mysql_query(sock, "SHOW DATABASES") ||
        !(tableres = mysql_store_result(sock)))
    {
      my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
                      MYF(0), mysql_error(sock));
      return 1;
    }
    while ((row = mysql_fetch_row(tableres)))
    {
      if (dump_all_views_in_db(row[0]))
        result=1;
    }
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2462 2463 2464 2465 2466 2467 2468 2469
  return result;
}
/* dump_all_databases */


static int dump_databases(char **db_names)
{
  int result=0;
2470 2471
  char **db;
  for (db= db_names ; *db ; db++)
2472
  {
2473
    if (dump_all_tables_in_db(*db))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2474 2475
      result=1;
  }
2476 2477 2478 2479 2480 2481 2482 2483
  if (!result && was_views)
  {
    for (db= db_names ; *db ; db++)
    {
      if (dump_all_views_in_db(*db))
        result=1;
    }
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2484 2485 2486 2487 2488 2489
  return result;
} /* dump_databases */


static int init_dumping(char *database)
{
2490
  if (mysql_get_server_version(sock) >= 50003 &&
2491 2492
      !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
    return 1; 
2493

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2494 2495
  if (mysql_select_db(sock, database))
  {
2496
    DB_error(sock, "when selecting the database");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2497 2498
    return 1;			/* If --force */
  }
2499
  if (!path && !opt_xml)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2500 2501 2502
  {
    if (opt_databases || opt_alldbs)
    {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2503
      /*
paul@kite-hub.kitebird.com's avatar
paul@kite-hub.kitebird.com committed
2504
	length of table name * 2 (if name contains quotes), 2 quotes and 0
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2505
      */
2506 2507
      char quoted_database_buf[64*2+3];
      char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
2508
      if (opt_comments)
2509
      {
monty@mysql.com's avatar
monty@mysql.com committed
2510
	fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
2511 2512
	check_io(md_result_file);
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2513
      if (!opt_create_db)
2514
      {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2515
        char qbuf[256];
2516 2517
        MYSQL_ROW row;
        MYSQL_RES *dbinfo;
2518

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

2523
        if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock)))
2524 2525
        {
          /* Old server version, dump generic CREATE DATABASE */
2526 2527 2528 2529
          if (opt_drop_database)
            fprintf(md_result_file,
                    "\n/*!40000 DROP DATABASE IF EXISTS %s;*/\n",
                    qdatabase);
2530
	  fprintf(md_result_file,
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2531 2532
		  "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
		  qdatabase);
2533 2534 2535
	}
	else
        {
2536 2537 2538 2539
          if (opt_drop_database)
            fprintf(md_result_file,
                    "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
                    qdatabase);
2540 2541 2542 2543 2544 2545 2546
	  row = mysql_fetch_row(dbinfo);
	  if (row[1])
	  {
	    fprintf(md_result_file,"\n%s;\n",row[1]);
          }
	}
      }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2547
      fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
2548
      check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2549 2550
    }
  }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2551 2552
  if (extended_insert && init_dynamic_string(&extended_row, "", 1024, 1024))
    exit(EX_EOM);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2553 2554 2555 2556
  return 0;
} /* init_dumping */


2557 2558
my_bool include_table(byte* hash_key, uint len)
{
serg@serg.mylan's avatar
serg@serg.mylan committed
2559
  if (hash_search(&ignore_table, (byte*) hash_key, len))
2560 2561 2562 2563 2564
    return FALSE;

  return TRUE;
}

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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2566 2567 2568 2569
static int dump_all_tables_in_db(char *database)
{
  char *table;
  uint numrows;
2570
  char table_buff[NAME_LEN*2+3];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2571

2572 2573 2574 2575 2576 2577
  char hash_key[2*NAME_LEN+2];  /* "db.tablename" */
  char *afterdot;

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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2578 2579
  if (init_dumping(database))
    return 1;
2580
  if (opt_xml)
2581
    print_xml_tag1(md_result_file, "", "database name=", database, "\n");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2582 2583 2584 2585
  if (lock_tables)
  {
    DYNAMIC_STRING query;
    init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
2586
    for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2587
    {
2588
      dynstr_append(&query, quote_name(table, table_buff, 1));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2589 2590 2591
      dynstr_append(&query, " READ /*!32311 LOCAL */,");
    }
    if (numrows && mysql_real_query(sock, query.str, query.length-1))
2592
      DB_error(sock, "when using LOCK TABLES");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2593 2594 2595 2596 2597 2598
            /* We shall continue here, if --force was given */
    dynstr_free(&query);
  }
  if (flush_logs)
  {
    if (mysql_refresh(sock, REFRESH_LOG))
2599
      DB_error(sock, "when doing refresh");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2600 2601
           /* We shall continue here, if --force was given */
  }
2602
  while ((table= getTableName(0)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2603
  {
2604 2605 2606
    char *end= strmov(afterdot, table);
    if (include_table(hash_key, end - hash_key))
    {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2607
      dump_table(table,database);
2608 2609
      my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
      order_by= 0;
2610 2611 2612
      if (opt_dump_triggers && ! opt_xml &&
          mysql_get_server_version(sock) >= 50009)
        dump_triggers_for_table(table, database);
2613
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2614
  }
2615 2616 2617 2618 2619 2620
  if (opt_routines && !opt_xml &&
      mysql_get_server_version(sock) >= 50009)
  {
    DBUG_PRINT("info", ("Dumping routines for database %s", database));
    dump_routines_for_db(database);
  }
2621
  if (opt_xml)
2622
  {
2623
    fputs("</database>\n", md_result_file);
2624 2625
    check_io(md_result_file);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2626
  if (lock_tables)
2627
    mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2628 2629 2630 2631
  return 0;
} /* dump_all_tables_in_db */


2632 2633 2634 2635 2636 2637
/*
   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
2638

2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663
  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];

  if (init_dumping(database))
    return 1;
  if (opt_xml)
    print_xml_tag1(md_result_file, "", "database name=", database, "\n");
  if (lock_tables)
  {
    DYNAMIC_STRING query;
    init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
    for (numrows= 0 ; (table= getTableName(1)); numrows++)
    {
      dynstr_append(&query, quote_name(table, table_buff, 1));
      dynstr_append(&query, " READ /*!32311 LOCAL */,");
    }
    if (numrows && mysql_real_query(sock, query.str, query.length-1))
2664
      DB_error(sock, "when using LOCK TABLES");
2665 2666 2667 2668 2669 2670
            /* We shall continue here, if --force was given */
    dynstr_free(&query);
  }
  if (flush_logs)
  {
    if (mysql_refresh(sock, REFRESH_LOG))
2671
      DB_error(sock, "when doing refresh");
2672 2673 2674
           /* We shall continue here, if --force was given */
  }
  while ((table= getTableName(0)))
2675
     get_view_structure(table, database);
2676 2677 2678 2679 2680 2681 2682 2683 2684
  if (opt_xml)
  {
    fputs("</database>\n", md_result_file);
    check_io(md_result_file);
  }
  if (lock_tables)
    mysql_query(sock,"UNLOCK TABLES");
  return 0;
} /* dump_all_tables_in_db */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2685

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

2687
/*
2688 2689 2690 2691
  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 
  different case (e.g.  T1 vs t1)
2692 2693
  
  RETURN
2694
    int - 0 if a tablename was retrieved.  1 if not
2695 2696
*/

2697
static int get_actual_table_name(const char *old_table_name, 
2698 2699 2700
                                  char *new_table_name, 
                                  int buf_size)
{
2701
  int retval;
2702
  MYSQL_RES  *table_res;
2703
  MYSQL_ROW  row;
2704
  char query[50 + 2*NAME_LEN];
2705
  char show_name_buff[FN_REFLEN];
2706
  DBUG_ENTER("get_actual_table_name");
2707

2708 2709 2710 2711 2712
  /* Check memory for quote_for_like() */
  DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
  my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", 
	      quote_for_like(old_table_name, show_name_buff));

2713 2714 2715 2716
  if (mysql_query_with_error_report(sock, 0, query))
  {
    safe_exit(EX_MYSQLERR);
  }
2717

2718
  retval = 1;
2719 2720
  
  if ((table_res= mysql_store_result(sock)))
2721
  {
2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733
    my_ulonglong num_rows= mysql_num_rows(table_res);
    if (num_rows > 0)
    {
      /*
        Return first row
        TODO: Return all matching rows
      */
      row= mysql_fetch_row(table_res);
      strmake(new_table_name, row[0], buf_size-1);
      retval= 0;
    }
    mysql_free_result(table_res);
2734
  }
2735
  return retval;
2736
}
2737

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2738 2739 2740

static int dump_selected_tables(char *db, char **table_names, int tables)
{
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2741
  uint i;
2742
  char table_buff[NAME_LEN*+3];
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2743 2744 2745
  char new_table_name[NAME_LEN];
  DYNAMIC_STRING lock_tables_query;
  HASH dump_tables;
2746
  char *table_name;
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2747
  DBUG_ENTER("dump_selected_tables");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2748 2749 2750

  if (init_dumping(db))
    return 1;
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2751 2752 2753

  /* Init hash table for storing the actual name of tables to dump */
  if (hash_init(&dump_tables, charset_info, 16, 0, 0,
monty@mysql.com's avatar
monty@mysql.com committed
2754
                 (hash_get_key) get_table_key, (hash_free_key) free_table_ent,
monty@mishka.local's avatar
monty@mishka.local committed
2755
                0))
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2756 2757 2758 2759
    exit(EX_EOM);

  init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024);
  for (; tables > 0 ; tables-- , table_names++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2760
  {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2761
    /* the table name passed on commandline may be wrong case */
monty@mishka.local's avatar
monty@mishka.local committed
2762
    if (!get_actual_table_name(*table_names,
monty@mysql.com's avatar
monty@mysql.com committed
2763
                               new_table_name, sizeof(new_table_name)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2764
    {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2765 2766 2767 2768 2769 2770 2771
      /* Add found table name to lock_tables_query */
      if (lock_tables)
      {
        dynstr_append(&lock_tables_query,
                      quote_name(new_table_name, table_buff, 1));
        dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,");
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2772

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2773 2774 2775 2776 2777
      /* Add found table name to dump_tables list */
      if (my_hash_insert(&dump_tables,
                         (byte*)my_strdup(new_table_name, MYF(0))))
        exit(EX_EOM);

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2778
    }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2779
    else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2780
    {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2781 2782 2783 2784
       my_printf_error(0,"Couldn't find table: \"%s\"\n", MYF(0),
                       *table_names);
       safe_exit(EX_ILLEGAL_TABLE);
       /* We shall countinue here, if --force was given */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2785
    }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2786 2787 2788 2789 2790 2791
  }

  if (lock_tables)
  {
    if (mysql_real_query(sock, lock_tables_query.str,
                         lock_tables_query.length-1))
2792
      DB_error(sock, "when doing LOCK TABLES");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2793 2794
       /* We shall countinue here, if --force was given */
  }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2795
  dynstr_free(&lock_tables_query);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2796 2797 2798
  if (flush_logs)
  {
    if (mysql_refresh(sock, REFRESH_LOG))
2799
      DB_error(sock, "when doing refresh");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2800 2801
     /* We shall countinue here, if --force was given */
  }
2802
  if (opt_xml)
2803
    print_xml_tag1(md_result_file, "", "database name=", db, "\n");
2804

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2805
  /* Dump each selected table */
2806
  for (i= 0; i < dump_tables.records; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2807
  {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2808 2809
    table_name= hash_element(&dump_tables, i);
    DBUG_PRINT("info",("Dumping table %s", table_name));
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2810
    dump_table(table_name,db);
2811 2812 2813
    if (opt_dump_triggers &&
        mysql_get_server_version(sock) >= 50009)
      dump_triggers_for_table(table_name, db);
2814
  }
2815 2816

  /* Dump each selected view */
2817 2818
  if (was_views)
  {
2819 2820 2821 2822
    for(i=0; i < dump_tables.records; i++)
    {
      table_name= hash_element(&dump_tables, i);
      get_view_structure(table_name, db);
msvensson@neptunus.(none)'s avatar
msvensson@neptunus.(none) committed
2823
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2824
  }
2825 2826 2827 2828 2829 2830 2831
  /* obtain dump of routines (procs/functions) */
  if (opt_routines  && !opt_xml &&
      mysql_get_server_version(sock) >= 50009)
  {
    DBUG_PRINT("info", ("Dumping routines for database %s", db));
    dump_routines_for_db(db);
  }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2832 2833 2834
  hash_free(&dump_tables);
  my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
  order_by= 0;
2835
  if (opt_xml)
2836
  {
2837
    fputs("</database>\n", md_result_file);
2838 2839
    check_io(md_result_file);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2840
  if (lock_tables)
2841
    mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2842
  DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2843 2844 2845
} /* dump_selected_tables */


2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862
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"))
  {
    my_printf_error(0, "Error: Couldn't execute 'SHOW MASTER STATUS': %s",
                    MYF(0), mysql_error(mysql_con));
    return 1;
  }
  else
  {
    row = mysql_fetch_row(master);
    if (row && row[0] && row[1])
    {
2863
      /* SHOW MASTER STATUS reports file and position */
2864 2865 2866 2867 2868 2869 2870 2871 2872
      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",
              comment_prefix, row[0], row[1]); 
      check_io(md_result_file);
    }
2873 2874 2875 2876
    else if (!ignore_errors)
    {
      /* SHOW MASTER STATUS reports nothing and --force is not enabled */
      my_printf_error(0, "Error: Binlogging on server not active", 
2877
		      MYF(0));
2878 2879 2880
      mysql_free_result(master);
      return 1;
    }
2881 2882 2883 2884 2885 2886 2887 2888
    mysql_free_result(master);
  }
  return 0;
}


static int do_flush_tables_read_lock(MYSQL *mysql_con)
{
2889 2890 2891 2892 2893 2894 2895 2896
  /*
    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.
  */
2897
  return 
2898 2899 2900
    ( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") ||
      mysql_query_with_error_report(mysql_con, 0,
                                    "FLUSH TABLES WITH READ LOCK") );
2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921
}


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


static int do_reset_master(MYSQL *mysql_con)
{
  return mysql_query_with_error_report(mysql_con, 0, "RESET MASTER");
}


static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now)
{
  /*
    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).
2922 2923 2924 2925

    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).
2926 2927
  */
  return (mysql_query_with_error_report(mysql_con, 0,
2928 2929 2930
                                        "SET SESSION TRANSACTION ISOLATION "
                                        "LEVEL REPEATABLE READ") ||
          mysql_query_with_error_report(mysql_con, 0,
2931 2932 2933 2934 2935 2936
                                        consistent_read_now ?
                                        "START TRANSACTION "
                                        "WITH CONSISTENT SNAPSHOT" :
                                        "BEGIN"));
}

2937 2938 2939 2940 2941 2942 2943 2944 2945

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

2946
  *err_pos= 0;                  /* No error yet */
2947
  while (end > x && my_isspace(charset_info, end[-1]))
2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978
    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
2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995
/* Print a value with a prefix on file */
static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
			const char *prefix, const char *name,
			int string_value)
{
  MYSQL_FIELD	*field;
  mysql_field_seek(result, 0);

  for ( ; (field = mysql_fetch_field(result)) ; row++)
  {
    if (!strcmp(field->name,name))
    {
      if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
      {
	fputc(' ',file);
	fputs(prefix, file);
	if (string_value)
2996
	  unescape(file,row[0],(uint) strlen(row[0]));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2997 2998
	else
	  fputs(row[0], file);
2999
	check_io(file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3000 3001 3002 3003 3004 3005 3006 3007
	return;
      }
    }
  }
  return;					/* This shouldn't happen */
} /* print_value */


3008 3009 3010
/*

  SYNOPSIS
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3011 3012 3013 3014 3015 3016 3017 3018 3019 3020

  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
  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 
  supported, 1 if it is supported.

  ARGS

3021 3022
    check_if_ignore_table()
    table_name			Table name to check
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3023
    table_type                  Type of table
3024 3025 3026 3027 3028 3029

  GLOBAL VARIABLES
    sock			MySQL socket
    verbose			Write warning messages

  RETURN
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3030
    char (bit value)            See IGNORE_ values at top
3031 3032
*/

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3033
char check_if_ignore_table(const char *table_name, char *table_type)
3034
{
3035
  char result= IGNORE_NONE;
3036 3037 3038
  char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
  MYSQL_RES *res;
  MYSQL_ROW row;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3039
  DBUG_ENTER("check_if_ignore_table");
3040

3041 3042 3043 3044
  /* 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",
	      quote_for_like(table_name, show_name_buff));
3045
  if (mysql_query_with_error_report(sock, &res, buff))
3046 3047 3048 3049 3050 3051 3052
  {
    if (mysql_errno(sock) != ER_PARSE_ERROR)
    {					/* If old MySQL version */
      if (verbose)
	fprintf(stderr,
		"-- Warning: Couldn't get status information for table %s (%s)\n",
		table_name,mysql_error(sock));
3053
      DBUG_RETURN(result);                       /* assume table is ok */
3054 3055
    }
  }
3056
  if (!(row= mysql_fetch_row(res)))
3057 3058 3059 3060
  {
    fprintf(stderr,
	    "Error: Couldn't read status information for table %s (%s)\n",
	    table_name, mysql_error(sock));
3061
    mysql_free_result(res);
3062
    DBUG_RETURN(result);                         /* assume table is ok */
3063
  }
3064
  if (!(row[1]))
monty@mysql.com's avatar
monty@mysql.com committed
3065
    strmake(table_type, "VIEW", NAME_LEN-1);
3066 3067
  else
  {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3068 3069 3070 3071 3072 3073
    /*
      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
    */
3074
    strmake(table_type, row[1], NAME_LEN-1);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090
    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
    */
    if (!dFlag &&
        (!strcmp(table_type,"MRG_MyISAM") || !strcmp(table_type,"MRG_ISAM")))
      result= IGNORE_DATA;
3091
  }
3092
  mysql_free_result(res);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3093
  DBUG_RETURN(result);
3094 3095
}

3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112
/*
  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
3113

3114 3115 3116 3117 3118 3119
static char *primary_key_fields(const char *table_name)
{
  MYSQL_RES  *res = NULL;
  MYSQL_ROW  row;
  /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
  char show_keys_buff[15 + 64 * 2 + 3];
tsmith@build.mysql.com's avatar
tsmith@build.mysql.com committed
3120
  uint result_length = 0;
3121 3122
  char *result = 0;

3123 3124
  my_snprintf(show_keys_buff, sizeof(show_keys_buff), 
	      "SHOW KEYS FROM %s", table_name);
3125 3126 3127 3128 3129 3130 3131 3132 3133 3134
  if (mysql_query(sock, show_keys_buff) ||
      !(res = mysql_store_result(sock)))
  {
    fprintf(stderr, "Warning: Couldn't read keys from table %s;"
            " records are NOT sorted (%s)\n",
            table_name, mysql_error(sock));
    /* 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
3135 3136 3137 3138 3139 3140 3141
  /*
   * 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.
   */
  if ((row = mysql_fetch_row(res)) && atoi(row[1]) == 0)
3142
  {
tsmith@build.mysql.com's avatar
tsmith@build.mysql.com committed
3143 3144 3145 3146
    /* Key is unique */
    do
      result_length += strlen(row[4]) + 1;      /* + 1 for ',' or \0 */
    while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1);
3147 3148 3149
  }

  /* Build the ORDER BY clause result */
monty@mishka.local's avatar
monty@mishka.local committed
3150 3151
  if (result_length)
  {
3152 3153 3154
    char *end;
    /* result (terminating \0 is already in result_length) */
    result = my_malloc(result_length + 10, MYF(MY_WME));
monty@mishka.local's avatar
monty@mishka.local committed
3155 3156
    if (!result)
    {
3157 3158 3159
      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
3160
    mysql_data_seek(res, 0);
3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173
    row = mysql_fetch_row(res);
    end = strmov(result, row[4]);
    while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1)
      end = strxmov(end, ",", row[4], NullS);
  }

cleanup:
  if (res)
    mysql_free_result(res);

  return result;
}

3174

3175 3176 3177 3178
/*
  Getting VIEW structure

  SYNOPSIS
3179
    get_view_structure()
3180 3181 3182 3183 3184 3185 3186 3187
    table   view name
    db      db name

  RETURN
    0 OK
    1 ERROR
*/

3188
static my_bool get_view_structure(char *table, char* db)
3189
{
3190
  MYSQL_RES  *table_res;
3191 3192 3193 3194 3195 3196 3197
  MYSQL_ROW  row;
  MYSQL_FIELD *field;
  char	     *result_table, *opt_quoted_table;
  char	     table_buff[NAME_LEN*2+3];
  char	     table_buff2[NAME_LEN*2+3];
  char       buff[20+FN_REFLEN];
  FILE       *sql_file = md_result_file;
3198
  DBUG_ENTER("get_view_structure");
3199 3200 3201 3202 3203 3204 3205

  if (tFlag)
    DBUG_RETURN(0);

  if (verbose)
    fprintf(stderr, "-- Retrieving view structure for table %s...\n", table);

jimw@mysql.com's avatar
jimw@mysql.com committed
3206
#ifdef NOT_REALLY_USED_YET
3207 3208
  sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
	  (opt_quoted || opt_keywords));
jimw@mysql.com's avatar
jimw@mysql.com committed
3209 3210
#endif

3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235
  result_table=     quote_name(table, table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);

  sprintf(buff,"show create table %s", result_table);
  if (mysql_query(sock, buff))
  {
    fprintf(stderr, "%s: Can't get CREATE TABLE for view %s (%s)\n",
            my_progname, result_table, mysql_error(sock));
    safe_exit(EX_MYSQLERR);
    DBUG_RETURN(0);
  }

  if (path)
  {
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
    convert_dirname(tmp_path,path,NullS);
    sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
                       O_WRONLY, MYF(MY_WME));
    if (!sql_file)			/* If file couldn't be opened */
    {
      safe_exit(EX_MYSQLERR);
      DBUG_RETURN(1);
    }
    write_header(sql_file, db);
  }
3236 3237
  table_res= mysql_store_result(sock);
  field= mysql_fetch_field_direct(table_res, 0);
3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252
  if (strcmp(field->name, "View") != 0)
  {
    if (verbose)
      fprintf(stderr, "-- It's base table, skipped\n");
    DBUG_RETURN(0);
  }

  if (!opt_xml && opt_comments)
  {
    fprintf(sql_file, "\n--\n-- View structure for view %s\n--\n\n",
            result_table);
    check_io(sql_file);
  }
  if (opt_drop)
  {
3253 3254 3255 3256
    fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n",
            opt_quoted_table);
    fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
            opt_quoted_table);
3257 3258 3259
    check_io(sql_file);
  }

3260
  row= mysql_fetch_row(table_res);
3261
  fprintf(sql_file, "/*!50001 %s*/;\n", row[1]);
3262
  check_io(sql_file);
3263
  mysql_free_result(table_res);
3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274

  if (sql_file != md_result_file)
  {
    fputs("\n", sql_file);
    write_footer(sql_file);
    my_fclose(sql_file, MYF(MY_WME));
  }
  DBUG_RETURN(0);
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
3275 3276
int main(int argc, char **argv)
{
3277 3278
  MY_INIT("mysqldump");

3279
  compatible_mode_normal_str[0]= 0;
3280
  default_charset= (char *)mysql_universal_client_charset;
monty@mishka.local's avatar
monty@mishka.local committed
3281
  bzero((char*) &ignore_table, sizeof(ignore_table));
3282

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3283 3284 3285 3286 3287
  if (get_options(&argc, &argv))
  {
    my_end(0);
    exit(EX_USAGE);
  }
3288
  if (dbConnect(current_host, current_user, opt_password))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3289 3290
    exit(EX_MYSQLERR);
  if (!path)
3291 3292
    write_header(md_result_file, *argv);

3293 3294 3295 3296 3297 3298 3299 3300
  if ((opt_lock_all_tables || opt_master_data) &&
      do_flush_tables_read_lock(sock))
    goto err;
  if (opt_single_transaction && start_transaction(sock, test(opt_master_data)))
      goto err;
  if (opt_delete_master_logs && do_reset_master(sock))
    goto err;
  if (opt_lock_all_tables || opt_master_data)
3301
  {
3302 3303 3304
    if (flush_logs && mysql_refresh(sock, REFRESH_LOG))
      goto err;
    flush_logs= 0; /* not anymore; that would not be sensible */
3305
  }
3306 3307
  if (opt_master_data && do_show_master_status(sock))
    goto err;
3308
  if (opt_single_transaction && do_unlock_tables(sock)) /* unlock but no commit! */
3309 3310
    goto err;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3311 3312 3313
  if (opt_alldbs)
    dump_all_databases();
  else if (argc > 1 && !opt_databases)
3314 3315
  {
    /* Only one database and selected table(s) */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3316
    dump_selected_tables(*argv, (argv + 1), (argc - 1));
3317
  }
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
3318
  else
3319 3320
  {
    /* One or more databases, all tables */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3321
    dump_databases(argv);
3322
  }
3323 3324 3325
#ifdef HAVE_SMEM
  my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif
3326 3327 3328 3329 3330 3331 3332
  /*
    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
3333
  dbDisconnect(current_host);
3334 3335
  if (!path)
    write_footer(md_result_file);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
3336 3337
  if (md_result_file != stdout)
    my_fclose(md_result_file, MYF(0));
3338
  my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
monty@mishka.local's avatar
monty@mishka.local committed
3339 3340
  if (hash_inited(&ignore_table))
    hash_free(&ignore_table);
3341
  if (extended_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3342
    dynstr_free(&extended_row);
3343 3344
  if (insert_pat_inited)
    dynstr_free(&insert_pat);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3345 3346 3347
  my_end(0);
  return(first_error);
} /* main */