mysqldump.c 111 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
** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
** DATE:   December 3, 1994
** WARRANTY: None, expressed, impressed, implied
24
**          or other
25 26 27 28 29 30 31 32
** 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
#include <my_sys.h>
44
#include <my_user.h>
bk@work.mysql.com's avatar
bk@work.mysql.com committed
45 46
#include <m_string.h>
#include <m_ctype.h>
47
#include <hash.h>
bk@work.mysql.com's avatar
bk@work.mysql.com committed
48

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

/* Exit codes */

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

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

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

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

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

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

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

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

154
HASH ignore_table;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
155

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

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

static void safe_exit(int error);
412
static void write_header(FILE *sql_file, char *db_name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
413
static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
414 415
                        const char *prefix,const char *name,
                        int string_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
416 417 418 419 420
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();
421
static char *quote_name(const char *name, char *buff, my_bool force);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
422
char check_if_ignore_table(const char *table_name, char *table_type);
423
static char *primary_key_fields(const char *table_name);
424
static my_bool get_view_structure(char *table, char* db);
425
static my_bool dump_all_views_in_db(char *database);
426

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

429 430
/*
  exit with message if ferror(file)
431

432 433
  SYNOPSIS
    check_io()
434
    file        - checked file
435 436 437 438 439 440 441
*/

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

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


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

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

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


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

486

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

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

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

540

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

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

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

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

578

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


serg@serg.mylan's avatar
serg@serg.mylan committed
587
void init_table_rule_hash(HASH* h)
588
{
monty@mishka.local's avatar
monty@mishka.local committed
589 590 591
  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
592
    exit(EX_EOM);
593 594
}

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

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

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

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

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

756
  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
757
    exit(ho_error);
758

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

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


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


825 826 827 828 829 830 831
/*
  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
832
    res             if non zero, result will be put there with
833
                    mysql_store_result()
834 835 836 837 838 839
    query           query to send to server

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

841 842 843 844 845 846 847 848 849 850 851 852 853 854
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;
}

855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
/*
  Open a new .sql file to dump the table or view into

  SYNOPSIS
    open_sql_file_for_table
    name      name of the table or view

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

876

bk@work.mysql.com's avatar
bk@work.mysql.com committed
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
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)
{
895
  char buff[20+FN_REFLEN];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
896 897 898
  DBUG_ENTER("dbConnect");
  if (verbose)
  {
899
    fprintf(stderr, "-- Connecting to %s...\n", host ? host : "localhost");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
900 901 902 903 904 905 906
  }
  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,
907
                  opt_ssl_capath, opt_ssl_cipher);
908 909
  mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
                (char*)&opt_ssl_verify_server_cert);
910 911 912 913 914 915
#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
916
#endif
917
  mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
918 919 920 921
  if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd,
         NULL,opt_mysql_port,opt_mysql_unix_port,
         0)))
  {
922
    DB_error(&mysql_connection, "when trying to connect");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
923 924
    return 1;
  }
bar@mysql.com's avatar
bar@mysql.com committed
925 926 927 928 929
  /*
    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;
930 931 932 933 934
  /*
    As we're going to set SQL_MODE, it would be lost on reconnect, so we
    cannot reconnect.
  */
  sock->reconnect= 0;
935
  my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */",
936
              compatible_mode_normal_str);
937
  if (mysql_query_with_error_report(sock, 0, buff))
938 939 940 941 942
  {
    mysql_close(sock);
    safe_exit(EX_MYSQLERR);
    return 1;
  }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
943
  /*
944
    set time_zone to UTC to allow dumping date types between servers with
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
945 946 947 948 949 950 951 952 953 954 955 956
    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
957 958 959 960 961 962 963 964 965 966
  return 0;
} /* dbConnect */


/*
** dbDisconnect -- disconnects from the host.
*/
static void dbDisconnect(char *host)
{
  if (verbose)
967
    fprintf(stderr, "-- Disconnecting from %s...\n", host ? host : "localhost");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
968 969 970 971 972 973 974 975 976 977
  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))))
  {
978 979
    ignore_errors=0;                            /* Fatal error */
    safe_exit(EX_MYSQLERR);                     /* Force exit */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
980
  }
981
  mysql_real_escape_string(&mysql_connection, tmp, pos, length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
982 983 984
  fputc('\'', file);
  fputs(tmp, file);
  fputc('\'', file);
985
  check_io(file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
986 987 988 989 990 991 992 993 994
  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++)
995
    if (!my_isvar(charset_info,*str) && *str != '$')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
996 997 998 999 1000
      return 1;
#endif
  return 0;
} /* test_if_special_chars */

1001

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

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1003 1004 1005
/*
  quote_name(name, buff, force)

1006
  Quotes char string, taking into account compatible mode
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1007 1008 1009 1010 1011

  Args

  name                 Unquoted string containing that which will be quoted
  buff                 The buffer that contains the quoted value, also returned
1012
  force                Flag to make it ignore 'test_if_special_chars'
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1013 1014 1015 1016 1017 1018

  Returns

  buff                 quoted string

*/
1019
static char *quote_name(const char *name, char *buff, my_bool force)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1020
{
1021
  char *to= buff;
1022 1023
  char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`';

1024 1025
  if (!force && !opt_quoted && !test_if_special_chars(name))
    return (char*) name;
1026
  *to++= qtype;
1027 1028
  while (*name)
  {
1029 1030
    if (*name == qtype)
      *to++= qtype;
1031 1032
    *to++= *name++;
  }
1033 1034
  to[0]= qtype;
  to[1]= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1035 1036 1037
  return buff;
} /* quote_name */

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

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

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1042
  SYNOPSIS
monty@mishka.local's avatar
monty@mishka.local committed
1043 1044 1045
    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
1046 1047 1048

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

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
    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"

*/
1061 1062 1063 1064 1065 1066
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
1067 1068 1069 1070 1071 1072 1073
    if (*name == '\\')
    {
      *to++='\\';
      *to++='\\';
      *to++='\\';
    }
    else if (*name == '\'' || *name == '_'  || *name == '%')
1074 1075 1076 1077 1078 1079 1080 1081 1082
      *to++= '\\';
    *to++= *name++;
  }
  to[0]= '\'';
  to[1]= 0;
  return buff;
}


1083 1084
/*
  Quote and print a string.
1085

1086 1087
  SYNOPSIS
    print_quoted_xml()
1088 1089 1090 1091
    output      - output file
    str         - string to print
    len         - its length

1092
  DESCRIPTION
1093
    Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
1094 1095 1096 1097 1098
*/

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

1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
  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;
    }
  }
1120
  check_io(xml_file);
1121 1122 1123 1124 1125
}


/*
  Print xml tag with one attribute.
1126

1127 1128
  SYNOPSIS
    print_xml_tag1()
1129 1130 1131 1132 1133 1134
    xml_file    - output file
    sbeg        - line beginning
    stag_atr    - tag and attribute
    sval        - value of attribute
    send        - line ending

1135 1136 1137 1138 1139 1140 1141 1142 1143
  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,
1144 1145
                           const char* stag_atr, const char* sval,
                           const char* send)
1146 1147 1148 1149 1150 1151 1152 1153
{
  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);
1154
  check_io(xml_file);
1155 1156 1157
}


1158 1159 1160 1161 1162
/*
  Print xml tag with for a field that is null

  SYNOPSIS
    print_xml_null_tag()
1163 1164 1165 1166 1167
    xml_file    - output file
    sbeg        - line beginning
    stag_atr    - tag and attribute
    sval        - value of attribute
    send        - line ending
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191

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


1192 1193 1194 1195 1196
/*
  Print xml tag with many attributes.

  SYNOPSIS
    print_xml_row()
1197 1198 1199 1200 1201
    xml_file    - output file
    row_name    - xml tag name
    tableRes    - query result
    row         - result row

1202 1203 1204 1205 1206 1207 1208 1209
  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,
1210
                          MYSQL_RES *tableRes, MYSQL_ROW *row)
1211 1212 1213 1214
{
  uint i;
  MYSQL_FIELD *field;
  ulong *lengths= mysql_fetch_lengths(tableRes);
1215

1216
  fprintf(xml_file, "\t\t<%s", row_name);
1217
  check_io(xml_file);
1218 1219 1220
  mysql_field_seek(tableRes, 0);
  for (i= 0; (field= mysql_fetch_field(tableRes)); i++)
  {
1221
    if ((*row)[i])
1222
    {
monty@mishka.local's avatar
monty@mishka.local committed
1223
      fputc(' ', xml_file);
1224
      print_quoted_xml(xml_file, field->name, field->name_length);
1225 1226
      fputs("=\"", xml_file);
      print_quoted_xml(xml_file, (*row)[i], lengths[i]);
monty@mishka.local's avatar
monty@mishka.local committed
1227
      fputc('"', xml_file);
1228
      check_io(xml_file);
1229 1230 1231
    }
  }
  fputs(" />\n", xml_file);
1232
  check_io(xml_file);
1233 1234
}

1235 1236 1237 1238 1239 1240 1241 1242
/*
  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

1243 1244 1245
  RETURN
    0  Success
    1  Error
1246 1247
*/

1248
static uint dump_routines_for_db(char *db)
1249
{
1250
  char       query_buff[512];
1251 1252 1253
  const char *routine_type[]= {"FUNCTION", "PROCEDURE"};
  char       db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
  char       *routine_name;
1254
  int        i;
1255
  FILE       *sql_file= md_result_file;
1256
  MYSQL_RES  *routine_res, *routine_list_res;
1257
  MYSQL_ROW  row, routine_list_row;
1258
  DBUG_ENTER("dump_routines_for_db");
1259
  DBUG_PRINT("enter", ("db: '%s'", db));
1260 1261 1262 1263 1264 1265

  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);
1266 1267

  /*
1268 1269
    not using "mysql_query_with_error_report" because we may have not
    enough privileges to lock mysql.proc.
1270
  */
1271
  if (lock_tables)
1272 1273
    mysql_query(sock, "LOCK TABLES mysql.proc READ");

1274
  fprintf(sql_file, "DELIMITER ;;\n");
1275 1276

  /* 0, retrieve and dump functions, 1, procedures */
1277
  for (i= 0; i <= 1; i++)
1278 1279 1280
  {
    my_snprintf(query_buff, sizeof(query_buff),
                "SHOW %s STATUS WHERE Db = '%s'",
1281
                routine_type[i], db_name_buff);
1282

1283
    if (mysql_query_with_error_report(sock, &routine_list_res, query_buff))
1284 1285 1286 1287 1288
      DBUG_RETURN(1);

    if (mysql_num_rows(routine_list_res))
    {

1289
      while ((routine_list_row= mysql_fetch_row(routine_list_res)))
1290
      {
1291 1292
        DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i],
                            name_buff));
1293
        routine_name= quote_name(routine_list_row[1], name_buff, 0);
1294
        my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s",
1295
                    routine_type[i], routine_name);
1296 1297 1298 1299

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

1300
        while ((row= mysql_fetch_row(routine_res)))
1301 1302
        {
          /*
1303 1304
            if the user has EXECUTE privilege he see routine names, but NOT the
            routine body of other routines that are not the creator of!
1305 1306
          */
          DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d",
1307
                             routine_name, row[2], strlen(row[2])));
1308 1309
          if (strlen(row[2]))
          {
1310 1311 1312
            char *query_str= NULL;
            char *definer_begin;

1313
            if (opt_drop)
1314
              fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n",
1315
                      routine_type[i], routine_name);
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326

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

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

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

1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346
            if (definer_begin)
            {
              char *definer_end= strstr(definer_begin, " PROCEDURE");

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

              if (definer_end)
              {
                char *query_str_tail;

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

                query_str_tail= strnmov(query_str, row[2],
                                        definer_begin - row[2]);
1347
                query_str_tail= strmov(query_str_tail, "*/ /*!50020");
1348 1349 1350 1351 1352 1353 1354
                query_str_tail= strnmov(query_str_tail, definer_begin,
                                        definer_end - definer_begin);
                query_str_tail= strxmov(query_str_tail, "*/ /*!50003",
                                        definer_end, NullS);
              }
            }

1355
            /*
1356 1357
              we need to change sql_mode only for the CREATE
              PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name
1358
            */;
1359
            fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n",
1360
                    row[1] /* sql_mode */);
1361 1362
            fprintf(sql_file, "/*!50003 %s */;;\n",
                    (query_str != NULL ? query_str : row[2]));
1363 1364 1365
            fprintf(sql_file,
                    "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/"
                    ";;\n");
1366 1367

            my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
1368 1369 1370 1371 1372 1373 1374
          }
        } /* 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)  */
1375 1376
  /* set the delimiter back to ';' */
  fprintf(sql_file, "DELIMITER ;\n");
1377

1378
  if (lock_tables)
1379
    VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
1380 1381
  DBUG_RETURN(0);
}
1382

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1383
/*
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1384 1385 1386 1387 1388 1389 1390
  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
1391
    table_type  - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW"
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1392
    ignore_flag - what we must particularly ignore - see IGNORE_ defines above
1393 1394 1395

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

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1398 1399
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
1400
{
monty@mysql.com's avatar
monty@mysql.com committed
1401
  my_bool    init=0, delayed, write_data, complete_insert;
1402
  my_ulonglong num_fields;
1403
  char       *result_table, *opt_quoted_table;
1404
  const char *insert_option;
1405 1406
  char       name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
  char       table_buff2[NAME_LEN*2+3], query_buff[512];
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
1407
  FILE       *sql_file = md_result_file;
1408
  int        len;
1409 1410 1411
  MYSQL_RES  *result;
  MYSQL_ROW  row;

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

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

monty@mysql.com's avatar
monty@mysql.com committed
1417 1418 1419 1420
  delayed= opt_delayed;
  if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED))
  {
    delayed= 0;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1421 1422
    if (verbose)
      fprintf(stderr,
monty@mysql.com's avatar
monty@mysql.com committed
1423 1424 1425
              "-- 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
1426

monty@mysql.com's avatar
monty@mysql.com committed
1427 1428
  complete_insert= 0;
  if ((write_data= !(*ignore_flag & IGNORE_DATA)))
1429
  {
monty@mysql.com's avatar
monty@mysql.com committed
1430
    complete_insert= opt_complete_insert;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1431 1432 1433 1434
    if (!insert_pat_inited)
      insert_pat_inited= init_dynamic_string(&insert_pat, "", 1024, 1024);
    else
      dynstr_set(&insert_pat, "");
1435 1436
  }

monty@mysql.com's avatar
monty@mysql.com committed
1437 1438
  insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
                  delayed ? " DELAYED " : opt_ignore ? " IGNORE " : "");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1439 1440

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

1443 1444 1445
  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
1446
  if (!create_options)
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1447 1448
    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
1449

1450 1451
  result_table=     quote_name(table, table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);
1452 1453

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

1456
  if (!opt_xml && !mysql_query_with_error_report(sock, 0, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1457
  {
1458 1459
    /* using SHOW CREATE statement */
    if (!tFlag)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1460
    {
1461 1462
      /* Make an sql-file, if path was given iow. option -T was given */
      char buff[20+FN_REFLEN];
1463
      MYSQL_FIELD *field;
1464

1465
      my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
1466
      if (mysql_query_with_error_report(sock, 0, buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1467
      {
1468 1469
        safe_exit(EX_MYSQLERR);
        DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1470 1471
      }

1472 1473
      if (path)
      {
1474
        if (!(sql_file= open_sql_file_for_table(table)))
1475
        {
1476 1477
          safe_exit(EX_MYSQLERR);
          DBUG_RETURN(0);
1478
        }
1479
        write_header(sql_file, db);
1480
      }
1481
      if (!opt_xml && opt_comments)
1482
      {
1483 1484 1485 1486
      if (strcmp (table_type, "VIEW") == 0)         /* view */
        fprintf(sql_file, "\n--\n-- Temporary table structure for view %s\n--\n\n",
                result_table);
      else
monty@mysql.com's avatar
monty@mysql.com committed
1487
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
1488 1489
                result_table);
        check_io(sql_file);
1490
      }
1491
      if (opt_drop)
1492
      {
1493 1494 1495 1496 1497 1498 1499
      /*
        Even if the "table" is a view, we do a DROP TABLE here.  The
        view-specific code below fills in the DROP VIEW.
       */
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
                opt_quoted_table);
        check_io(sql_file);
1500
      }
1501

1502 1503
      result= mysql_store_result(sock);
      field= mysql_fetch_field_direct(result, 0);
1504 1505
      if (strcmp(field->name, "View") == 0)
      {
1506 1507
        char *scv_buff = NULL;

1508
        if (verbose)
1509 1510
          fprintf(stderr, "-- It's a view, create dummy table for view\n");

1511 1512 1513 1514
        /* save "show create" statement for later */
        if ((row= mysql_fetch_row(result)) && (scv_buff=row[1]))
          scv_buff= my_strdup(scv_buff, MYF(0));

1515 1516 1517
        mysql_free_result(result);

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

1522 1523
          The properties of each column, aside from the data type, are not
          preserved in this temporary table, because they are not necessary.
1524

1525 1526 1527
          This will not be necessary once we can determine dependencies
          between views and can simply dump them in the appropriate order.
        */
1528
        my_snprintf(query_buff, sizeof(query_buff),
1529
                    "SHOW FIELDS FROM %s", result_table);
1530 1531
        if (mysql_query_with_error_report(sock, 0, query_buff))
        {
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
          /*
            View references invalid or privileged table/col/fun (err 1356),
            so we cannot create a stand-in table.  Be defensive and dump
            a comment with the view's 'show create' statement. (Bug #17371)
          */

          if (mysql_errno(sock) == ER_VIEW_INVALID)
            fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : "");

          my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));

1543
          safe_exit(EX_MYSQLERR);
1544
          DBUG_RETURN(0); 
1545
        }
1546 1547
        else
          my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
1548

1549
        if ((result= mysql_store_result(sock)))
1550
        {
1551 1552 1553 1554
          if (mysql_num_rows(result))
          {
            if (opt_drop)
            {
1555 1556 1557 1558 1559
            /*
              We have already dropped any table of the same name
              above, so here we just drop the view.
             */

1560 1561 1562 1563
              fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
                      opt_quoted_table);
              check_io(sql_file);
            }
1564

1565 1566 1567 1568 1569 1570 1571 1572
            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);

1573 1574
            fprintf(sql_file, "  %s %s", quote_name(row[0], name_buff, 0),
                    row[1]);
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584

            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);
          }
1585
        }
1586 1587
        mysql_free_result(result);

1588 1589 1590
        if (path)
          my_fclose(sql_file, MYF(MY_WME));

1591
        seen_views= 1;
1592 1593
        DBUG_RETURN(0);
      }
1594 1595

      row= mysql_fetch_row(result);
1596
      fprintf(sql_file, "%s;\n", row[1]);
1597
      check_io(sql_file);
1598
      mysql_free_result(result);
1599
    }
1600
    my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1601
                result_table);
1602
    if (mysql_query_with_error_report(sock, &result, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1603
    {
1604
      if (path)
1605
        my_fclose(sql_file, MYF(MY_WME));
1606 1607
      safe_exit(EX_MYSQLERR);
      DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1608
    }
1609

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1610
    /*
monty@mysql.com's avatar
monty@mysql.com committed
1611 1612 1613 1614
      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
1615
    */
monty@mysql.com's avatar
monty@mysql.com committed
1616
    if (write_data)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1617
    {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1618 1619 1620 1621
      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
1622
      if (complete_insert)
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1623 1624 1625 1626 1627 1628 1629 1630 1631
      {
        dynstr_append_mem(&insert_pat, " (", 2);
      }
      else
      {
        dynstr_append_mem(&insert_pat, " VALUES ", 8);
        if (!extended_insert)
          dynstr_append_mem(&insert_pat, "(", 1);
      }
1632 1633
    }

1634
    while ((row= mysql_fetch_row(result)))
1635
    {
monty@mysql.com's avatar
monty@mysql.com committed
1636
      if (complete_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1637
      {
monty@mysql.com's avatar
monty@mysql.com committed
1638 1639
        if (init)
        {
1640
          dynstr_append_mem(&insert_pat, ", ", 2);
monty@mysql.com's avatar
monty@mysql.com committed
1641 1642
        }
        init=1;
1643 1644
        dynstr_append(&insert_pat,
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
monty@mysql.com's avatar
monty@mysql.com committed
1645
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1646
    }
1647 1648
    num_fields= mysql_num_rows(result);
    mysql_free_result(result);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1649
  }
1650
  else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1651
  {
monty@mishka.local's avatar
monty@mishka.local committed
1652 1653 1654 1655
    if (verbose)
      fprintf(stderr,
              "%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
              my_progname, mysql_error(sock));
1656

1657
    my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
1658
                result_table);
1659
    if (mysql_query_with_error_report(sock, &result, query_buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1660 1661 1662 1663 1664
    {
      safe_exit(EX_MYSQLERR);
      DBUG_RETURN(0);
    }

1665 1666
    /* 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
1667
    {
1668
      if (path)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1669
      {
1670
        if (!(sql_file= open_sql_file_for_table(table)))
1671
        {
1672 1673
          safe_exit(EX_MYSQLERR);
          DBUG_RETURN(0);
1674
        }
1675
        write_header(sql_file, db);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1676
      }
1677
      if (!opt_xml && opt_comments)
1678 1679
        fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
                result_table);
1680
      if (opt_drop)
monty@mishka.local's avatar
monty@mishka.local committed
1681
        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
1682
      if (!opt_xml)
1683
        fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
1684
      else
1685
        print_xml_tag1(sql_file, "\t", "table_structure name=", table, "\n");
1686
      check_io(sql_file);
1687
    }
1688

monty@mysql.com's avatar
monty@mysql.com committed
1689
    if (write_data)
1690
    {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702
      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
1703
    }
1704

1705
    while ((row= mysql_fetch_row(result)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1706
    {
1707
      ulong *lengths= mysql_fetch_lengths(result);
1708
      if (init)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1709
      {
1710
        if (!opt_xml && !tFlag)
1711 1712 1713 1714
        {
          fputs(",\n",sql_file);
          check_io(sql_file);
        }
monty@mysql.com's avatar
monty@mysql.com committed
1715
        if (complete_insert)
1716
          dynstr_append_mem(&insert_pat, ", ", 2);
1717 1718
      }
      init=1;
monty@mysql.com's avatar
monty@mysql.com committed
1719
      if (opt_complete_insert)
1720 1721
        dynstr_append(&insert_pat,
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
1722 1723
      if (!tFlag)
      {
1724 1725 1726 1727 1728
        if (opt_xml)
        {
          print_xml_row(sql_file, "field", result, &row);
          continue;
        }
1729

1730
        if (opt_keywords)
1731 1732 1733
          fprintf(sql_file, "  %s.%s %s", result_table,
                  quote_name(row[SHOW_FIELDNAME],name_buff, 0),
                  row[SHOW_TYPE]);
1734
        else
1735 1736 1737
          fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
                                                  name_buff, 0),
                  row[SHOW_TYPE]);
1738 1739
        if (row[SHOW_DEFAULT])
        {
1740 1741
          fputs(" DEFAULT ", sql_file);
          unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
1742 1743
        }
        if (!row[SHOW_NULL][0])
1744
          fputs(" NOT NULL", sql_file);
1745
        if (row[SHOW_EXTRA][0])
1746 1747
          fprintf(sql_file, " %s",row[SHOW_EXTRA]);
        check_io(sql_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1748 1749
      }
    }
1750 1751
    num_fields= mysql_num_rows(result);
    mysql_free_result(result);
1752
    if (!tFlag)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1753
    {
1754 1755 1756
      /* Make an sql-file, if path was given iow. option -T was given */
      char buff[20+FN_REFLEN];
      uint keynr,primary_key;
1757
      my_snprintf(buff, sizeof(buff), "show keys from %s", result_table);
1758
      if (mysql_query_with_error_report(sock, &result, buff))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1759
      {
1760 1761 1762 1763 1764 1765 1766
        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",
1767
                my_progname, result_table, mysql_error(sock));
1768
        if (path)
1769
          my_fclose(sql_file, MYF(MY_WME));
1770 1771
        safe_exit(EX_MYSQLERR);
        DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1772
      }
1773 1774 1775 1776

      /* Find first which key is primary key */
      keynr=0;
      primary_key=INT_MAX;
1777
      while ((row= mysql_fetch_row(result)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1778
      {
1779 1780
        if (atoi(row[3]) == 1)
        {
1781
          keynr++;
1782
#ifdef FORCE_PRIMARY_KEY
1783 1784
          if (atoi(row[1]) == 0 && primary_key == INT_MAX)
            primary_key=keynr;
1785
#endif
1786 1787 1788 1789 1790
          if (!strcmp(row[2],"PRIMARY"))
          {
            primary_key=keynr;
            break;
          }
1791
        }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1792
      }
1793
      mysql_data_seek(result,0);
1794
      keynr=0;
1795
      while ((row= mysql_fetch_row(result)))
1796
      {
1797 1798 1799 1800 1801
        if (opt_xml)
        {
          print_xml_row(sql_file, "key", result, &row);
          continue;
        }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1802

1803 1804
        if (atoi(row[3]) == 1)
        {
1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
          if (keynr++)
            putc(')', sql_file);
          if (atoi(row[1]))       /* Test if duplicate key */
            /* Duplicate allowed */
            fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff,0));
          else if (keynr == primary_key)
            fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
          else
            fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff,
                                                            0));
1815 1816
        }
        else
1817
          putc(',', sql_file);
1818
        fputs(quote_name(row[4], name_buff, 0), sql_file);
1819
        if (row[7])
1820 1821
          fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
        check_io(sql_file);
1822
      }
1823 1824
      if (!opt_xml)
      {
1825 1826 1827 1828
        if (keynr)
          putc(')', sql_file);
        fputs("\n)",sql_file);
        check_io(sql_file);
1829
      }
1830 1831 1832

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

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

1840
        if (mysql_query_with_error_report(sock, &result, buff))
1841
        {
1842 1843 1844 1845 1846 1847 1848
          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",
                      result_table,mysql_error(sock));
          }
1849
        }
1850
        else if (!(row= mysql_fetch_row(result)))
1851
        {
1852 1853 1854
          fprintf(stderr,
                  "Error: Couldn't read status information for table %s (%s)\n",
                  result_table,mysql_error(sock));
1855 1856 1857
        }
        else
        {
1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868
          if (opt_xml)
            print_xml_row(sql_file, "options", result, &row);
          else
          {
            fputs("/*!",sql_file);
            print_value(sql_file,result,row,"engine=","Engine",0);
            print_value(sql_file,result,row,"","Create_options",0);
            print_value(sql_file,result,row,"comment=","Comment",1);
            fputs(" */",sql_file);
            check_io(sql_file);
          }
1869
        }
1870
        mysql_free_result(result);              /* Is always safe to free */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1871
      }
1872
continue_xml:
1873
      if (!opt_xml)
1874
        fputs(";\n", sql_file);
1875
      else
1876
        fputs("\t</table_structure>\n", sql_file);
1877
      check_io(sql_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1878 1879
    }
  }
monty@mysql.com's avatar
monty@mysql.com committed
1880
  if (opt_complete_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1881
  {
1882
    dynstr_append_mem(&insert_pat, ") VALUES ", 9);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1883
    if (!extended_insert)
1884
      dynstr_append_mem(&insert_pat, "(", 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1885
  }
1886
  if (sql_file != md_result_file)
1887 1888 1889
  {
    fputs("\n", sql_file);
    write_footer(sql_file);
1890
    my_fclose(sql_file, MYF(MY_WME));
1891
  }
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1892
  DBUG_RETURN(num_fields);
1893
} /* get_table_structure */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1894 1895


1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907
/*

  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)
{
1908 1909
  char       *result_table;
  char       name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
1910
  char       query_buff[512];
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1911
  uint old_opt_compatible_mode=opt_compatible_mode;
1912
  FILE       *sql_file = md_result_file;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1913 1914 1915
  MYSQL_RES  *result;
  MYSQL_ROW  row;

1916 1917
  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
1918 1919 1920

  /* Do not use ANSI_QUOTES on triggers in dump */
  opt_compatible_mode&= ~MASK_ANSI_QUOTES;
1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
  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\
1936
DELIMITER ;;\n");
1937
  while ((row= mysql_fetch_row(result)))
1938
  {
1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957
    fprintf(sql_file,
            "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n"
            "/*!50003 CREATE */ ",
            row[6] /* sql_mode */);

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

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

1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
      parse_user(row[7], strlen(row[7]), user_name_str, &user_name_len,
                 host_name_str, &host_name_len);

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

    fprintf(sql_file,
            "/*!50003 TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n\n",
1970 1971 1972 1973
            quote_name(row[0], name_buff, 0), /* Trigger */
            row[4], /* Timing */
            row[1], /* Event */
            result_table,
1974
            (strchr(" \t\n\r", *(row[3]))) ? "" : " ",
1975 1976 1977 1978
            row[3] /* Statement */);
  }
  if (mysql_num_rows(result))
    fprintf(sql_file,
1979 1980
            "DELIMITER ;\n"
            "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n");
1981
  mysql_free_result(result);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1982
  /*
1983
    make sure to set back opt_compatible mode to
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
1984 1985 1986
    original value
  */
  opt_compatible_mode=old_opt_compatible_mode;
1987 1988 1989
  DBUG_VOID_RETURN;
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1990
static char *add_load_option(char *ptr,const char *object,
1991
                             const char *statement)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1992 1993 1994
{
  if (object)
  {
1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
    /* 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
2005 2006 2007 2008 2009 2010
  }
  return ptr;
} /* add_load_option */


/*
2011 2012 2013 2014
  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
2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029
*/

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)
2030
        *to++= *from;      /* We want a duplicate of "'" for MySQL */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2031 2032 2033 2034 2035 2036 2037 2038 2039 2040
      end_backslashes=0;
    }
  }
  /* Add missing backslashes if user has specified odd number of backs.*/
  if (end_backslashes)
    *to++= '\\';
  return to;
} /* field_escape */


2041 2042 2043 2044 2045 2046
static char *alloc_query_str(ulong size)
{
  char *query;

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

2053

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2054
/*
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066

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

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2069
static void dump_table(char *table, char *db)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2070
{
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2071
  char ignore_flag;
2072
  char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3];
monty@mysql.com's avatar
monty@mysql.com committed
2073
  char table_type[NAME_LEN];
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2074
  char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
2075
  char *query= query_buf;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2076
  int error= 0;
2077
  ulong         rownr, row_break, total_length, init_length;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2078
  uint num_fields;
2079 2080 2081
  MYSQL_RES     *res;
  MYSQL_FIELD   *field;
  MYSQL_ROW     row;
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2082 2083 2084 2085 2086 2087
  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
2088
  num_fields= get_table_structure(table, db, table_type, &ignore_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2089

2090 2091 2092 2093 2094 2095
  /*
    The "table" could be a view.  If so, we don't do anything here.
  */
  if (strcmp (table_type, "VIEW") == 0)
    return;

2096 2097 2098 2099 2100 2101
  /* Check --no-data flag */
  if (dFlag)
  {
    if (verbose)
      fprintf(stderr,
              "-- Skipping dump data for table '%s', --no-data was used\n",
2102
              table);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2103
    DBUG_VOID_RETURN;
2104 2105
  }

monty@mysql.com's avatar
monty@mysql.com committed
2106 2107 2108
  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
2109 2110 2111 2112 2113 2114 2115 2116
  /*
    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,
2117 2118
              "-- Warning: Skipping data for table '%s' because it's of type %s\n",
              table, table_type);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2119 2120
    DBUG_VOID_RETURN;
  }
2121
  /* Check that there are any fields in the table */
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2122
  if (num_fields == 0)
2123 2124 2125
  {
    if (verbose)
      fprintf(stderr,
2126 2127
              "-- Skipping dump data for table '%s', it has no fields\n",
              table);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2128
    DBUG_VOID_RETURN;
2129 2130
  }

2131 2132
  result_table= quote_name(table,table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);
2133 2134 2135

  if (verbose)
    fprintf(stderr, "-- Sending SELECT query...\n");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2136 2137 2138
  if (path)
  {
    char filename[FN_REFLEN], tmp_path[FN_REFLEN];
2139
    convert_dirname(tmp_path,path,NullS);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2140 2141 2142
    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
2143
                                    filename wasn't deleted */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2144
    to_unix_path(filename);
2145 2146 2147
    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
2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158
    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';

2159
    my_snprintf(buff, sizeof(buff), " FROM %s", result_table);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2160
    end= strmov(end,buff);
2161
    if (where || order_by)
2162
    {
2163 2164 2165 2166 2167 2168 2169 2170 2171
      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);
2172 2173
    }
    if (mysql_real_query(sock, query, (uint) (end - query)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2174
    {
2175
      DB_error(sock, "when executing 'SELECT INTO OUTFILE'");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2176
      DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2177 2178 2179 2180
    }
  }
  else
  {
2181
    if (!opt_xml && opt_comments)
2182
    {
2183
      fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
2184
              result_table);
2185 2186
      check_io(md_result_file);
    }
2187
    my_snprintf(query, QUERY_LENGTH,
2188 2189
                "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
                result_table);
2190
    if (where || order_by)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2191
    {
2192 2193 2194 2195 2196 2197
      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)
2198
      {
2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213
        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);
2214
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2215
    }
2216
    if (!opt_xml && !opt_compact)
2217
    {
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2218
      fputs("\n", md_result_file);
2219 2220
      check_io(md_result_file);
    }
2221
    if (mysql_query_with_error_report(sock, 0, query))
2222
      DB_error(sock, "when retrieving data from server");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2223 2224 2225 2226 2227
    if (quick)
      res=mysql_use_result(sock);
    else
      res=mysql_store_result(sock);
    if (!res)
2228
    {
2229
      DB_error(sock, "when retrieving data from server");
2230 2231
      goto err;
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2232
    if (verbose)
2233
      fprintf(stderr, "-- Retrieving rows...\n");
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2234
    if (mysql_num_fields(res) != num_fields)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2235
    {
2236
      fprintf(stderr,"%s: Error in field count for table: %s !  Aborting.\n",
2237
              my_progname, result_table);
2238 2239
      error= EX_CONSCHECK;
      goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2240 2241
    }

jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2242
    if (opt_disable_keys)
2243
    {
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2244
      fprintf(md_result_file, "\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
2245
              opt_quoted_table);
2246 2247
      check_io(md_result_file);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2248
    if (opt_lock)
2249
    {
2250
      fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
2251 2252
      check_io(md_result_file);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2253

2254
    total_length= opt_net_buffer_length;                /* Force row break */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2255 2256
    row_break=0;
    rownr=0;
2257
    init_length=(uint) insert_pat.length+4;
2258
    if (opt_xml)
2259
      print_xml_tag1(md_result_file, "\t", "table_data name=", table, "\n");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2260

2261
    if (opt_autocommit)
2262
    {
2263
      fprintf(md_result_file, "set autocommit=0;\n");
2264 2265
      check_io(md_result_file);
    }
2266

2267
    while ((row= mysql_fetch_row(res)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2268 2269
    {
      uint i;
2270
      ulong *lengths= mysql_fetch_lengths(res);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2271
      rownr++;
2272
      if (!extended_insert && !opt_xml)
2273
      {
2274 2275
        fputs(insert_pat.str,md_result_file);
        check_io(md_result_file);
2276
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2277 2278
      mysql_field_seek(res,0);

jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2279
      if (opt_xml)
2280
      {
2281
        fputs("\t<row>\n", md_result_file);
2282
        check_io(md_result_file);
2283
      }
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2284

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2285 2286
      for (i = 0; i < mysql_num_fields(res); i++)
      {
2287
        int is_blob;
2288 2289
        ulong length= lengths[i];

2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304
        if (!(field = mysql_fetch_field(res)))
        {
          my_snprintf(query, QUERY_LENGTH,
                      "%s: Not enough fields from table %s! Aborting.\n",
                      my_progname, result_table);
          fputs(query,stderr);
          error= EX_CONSCHECK;
          goto err;
        }

        /*
           63 is my_charset_bin. If charsetnr is not 63,
           we have not a BLOB but a TEXT column.
           we'll dump in hex only BLOB columns.
        */
2305
        is_blob= (opt_hex_blob && field->charsetnr == 63 &&
2306 2307
                  (field->type == MYSQL_TYPE_BIT ||
                   field->type == MYSQL_TYPE_STRING ||
2308 2309 2310 2311 2312 2313
                   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;
2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339
        if (extended_insert)
        {
          if (i == 0)
            dynstr_set(&extended_row,"(");
          else
            dynstr_append(&extended_row,",");

          if (row[i])
          {
            if (length)
            {
              if (!IS_NUM_FIELD(field))
              {
                /*
                  "length * 2 + 2" is OK for both HEX and non-HEX modes:
                  - In HEX mode we need exactly 2 bytes per character
                  plus 2 bytes for '0x' prefix.
                  - In non-HEX mode we need up to 2 bytes per character,
                  plus 2 bytes for leading and trailing '\'' characters.
                */
                if (dynstr_realloc(&extended_row,length * 2+2))
                {
                  fputs("Aborting dump (out of memory)",stderr);
                  error= EX_EOM;
                  goto err;
                }
2340 2341 2342
                if (opt_hex_blob && is_blob)
                {
                  dynstr_append(&extended_row, "0x");
2343
                  extended_row.length+= mysql_hex_string(extended_row.str +
bar@mysql.com's avatar
bar@mysql.com committed
2344 2345 2346
                                                         extended_row.length,
                                                         row[i], length);
                  extended_row.str[extended_row.length]= '\0';
2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357
                }
                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,"'");
                }
2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408
              }
              else
              {
                /* change any strings ("inf", "-inf", "nan") into NULL */
                char *ptr = row[i];
                if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
                    my_isalpha(charset_info, ptr[1])))
                  dynstr_append(&extended_row, "NULL");
                else
                {
                  if (field->type == FIELD_TYPE_DECIMAL)
                  {
                    /* add " signs around */
                    dynstr_append(&extended_row, "'");
                    dynstr_append(&extended_row, ptr);
                    dynstr_append(&extended_row, "'");
                  }
                  else
                    dynstr_append(&extended_row, ptr);
                }
              }
            }
            else
              dynstr_append(&extended_row,"''");
          }
          else if (dynstr_append(&extended_row,"NULL"))
          {
            fputs("Aborting dump (out of memory)",stderr);
            error= EX_EOM;
            goto err;
          }
        }
        else
        {
          if (i && !opt_xml)
          {
            fputc(',', md_result_file);
            check_io(md_result_file);
          }
          if (row[i])
          {
            if (!IS_NUM_FIELD(field))
            {
              if (opt_xml)
              {
                print_xml_tag1(md_result_file, "\t\t", "field name=",
                              field->name, "");
                print_quoted_xml(md_result_file, row[i], length);
                fputs("</field>\n", md_result_file);
              }
              else if (opt_hex_blob && is_blob && length)
monty@mysql.com's avatar
monty@mysql.com committed
2409 2410
              {
                /* sakaik got the idea to to provide blob's in hex notation. */
2411
                char *ptr= row[i], *end= ptr + length;
2412
                fputs("0x", md_result_file);
monty@mysql.com's avatar
monty@mysql.com committed
2413
                for (; ptr < end ; ptr++)
2414
                  fprintf(md_result_file, "%02X", *((uchar *)ptr));
2415 2416
              }
              else
2417
                unescape(md_result_file, row[i], length);
2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
            }
            else
            {
              /* change any strings ("inf", "-inf", "nan") into NULL */
              char *ptr = row[i];
              if (opt_xml)
              {
                print_xml_tag1(md_result_file, "\t\t", "field name=",
                               field->name, "");
                fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
                      md_result_file);
                fputs("</field>\n", md_result_file);
              }
              else if (my_isalpha(charset_info, *ptr) ||
                       (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
                fputs("NULL", md_result_file);
              else if (field->type == FIELD_TYPE_DECIMAL)
              {
                /* add " signs around */
                fputc('\'', md_result_file);
                fputs(ptr, md_result_file);
                fputc('\'', md_result_file);
              }
              else
                fputs(ptr, md_result_file);
            }
          }
          else
2446 2447 2448 2449 2450 2451 2452 2453
          {
            /* 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
2454
          check_io(md_result_file);
2455
        }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2456 2457
      }

jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2458
      if (opt_xml)
2459
      {
2460
        fputs("\t</row>\n", md_result_file);
2461
        check_io(md_result_file);
2462
      }
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2463

2464
      if (extended_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2465
      {
2466 2467
        ulong row_length;
        dynstr_append(&extended_row,")");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2468
        row_length = 2 + extended_row.length;
2469
        if (total_length + row_length < opt_net_buffer_length)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2470
        {
2471 2472 2473 2474
          total_length += row_length;
          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
2475 2476
        else
        {
2477 2478 2479
          if (row_break)
            fputs(";\n", md_result_file);
          row_break=1;                          /* This is first row */
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2480

2481
          fputs(insert_pat.str,md_result_file);
2482
          fputs(extended_row.str,md_result_file);
2483
          total_length = row_length+init_length;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2484
        }
2485
        check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2486
      }
2487
      else if (!opt_xml)
2488
      {
2489 2490
        fputs(");\n", md_result_file);
        check_io(md_result_file);
2491
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2492
    }
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2493

2494
    /* XML - close table tag and supress regular output */
2495
    if (opt_xml)
2496
        fputs("\t</table_data>\n", md_result_file);
2497
    else if (extended_insert && row_break)
2498
      fputs(";\n", md_result_file);             /* If not empty table */
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2499
    fflush(md_result_file);
2500
    check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2501 2502
    if (mysql_errno(sock))
    {
2503
      my_snprintf(query, QUERY_LENGTH,
2504 2505 2506 2507 2508 2509
                  "%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
2510
      fputs(query,stderr);
2511 2512
      error= EX_CONSCHECK;
      goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2513 2514
    }
    if (opt_lock)
2515
    {
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2516
      fputs("UNLOCK TABLES;\n", md_result_file);
2517 2518
      check_io(md_result_file);
    }
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2519
    if (opt_disable_keys)
2520
    {
jani@hynda.mysql.fi's avatar
merge  
jani@hynda.mysql.fi committed
2521
      fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
2522
              opt_quoted_table);
2523 2524
      check_io(md_result_file);
    }
2525
    if (opt_autocommit)
2526
    {
2527
      fprintf(md_result_file, "commit;\n");
2528 2529
      check_io(md_result_file);
    }
2530
    mysql_free_result(res);
2531 2532
    if (query != query_buf)
      my_free(query, MYF(MY_ALLOW_ZERO_PTR));
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2533 2534
  }
  DBUG_VOID_RETURN;
2535 2536 2537 2538 2539

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
2540
  DBUG_VOID_RETURN;
2541
} /* dump_table */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555


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
2556

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573
  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;

2574
  if (mysql_query_with_error_report(sock, &tableres, "SHOW DATABASES"))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2575 2576 2577 2578 2579 2580
    return 1;
  while ((row = mysql_fetch_row(tableres)))
  {
    if (dump_all_tables_in_db(row[0]))
      result=1;
  }
2581
  if (seen_views)
2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595
  {
    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
2596 2597 2598 2599 2600 2601 2602 2603
  return result;
}
/* dump_all_databases */


static int dump_databases(char **db_names)
{
  int result=0;
2604 2605
  char **db;
  for (db= db_names ; *db ; db++)
2606
  {
2607
    if (dump_all_tables_in_db(*db))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2608 2609
      result=1;
  }
2610
  if (!result && seen_views)
2611 2612 2613 2614 2615 2616 2617
  {
    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
2618 2619 2620 2621 2622 2623
  return result;
} /* dump_databases */


static int init_dumping(char *database)
{
2624
  if (mysql_get_server_version(sock) >= 50003 &&
2625
      !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
2626
    return 1;
2627

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2628 2629
  if (mysql_select_db(sock, database))
  {
2630
    DB_error(sock, "when selecting the database");
2631
    return 1;                   /* If --force */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2632
  }
2633
  if (!path && !opt_xml)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2634 2635 2636
  {
    if (opt_databases || opt_alldbs)
    {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2637
      /*
2638
        length of table name * 2 (if name contains quotes), 2 quotes and 0
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2639
      */
2640 2641
      char quoted_database_buf[64*2+3];
      char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
2642
      if (opt_comments)
2643
      {
2644 2645
        fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
        check_io(md_result_file);
2646
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2647
      if (!opt_create_db)
2648
      {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2649
        char qbuf[256];
2650 2651
        MYSQL_ROW row;
        MYSQL_RES *dbinfo;
2652

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

2657
        if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock)))
2658 2659
        {
          /* Old server version, dump generic CREATE DATABASE */
2660 2661 2662 2663
          if (opt_drop_database)
            fprintf(md_result_file,
                    "\n/*!40000 DROP DATABASE IF EXISTS %s;*/\n",
                    qdatabase);
2664 2665 2666 2667 2668
          fprintf(md_result_file,
                  "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
                  qdatabase);
        }
        else
2669
        {
2670 2671 2672 2673
          if (opt_drop_database)
            fprintf(md_result_file,
                    "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n",
                    qdatabase);
2674 2675 2676 2677
          row = mysql_fetch_row(dbinfo);
          if (row[1])
          {
            fprintf(md_result_file,"\n%s;\n",row[1]);
2678
          }
2679
        }
2680
      }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2681
      fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
2682
      check_io(md_result_file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2683 2684
    }
  }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2685 2686
  if (extended_insert && init_dynamic_string(&extended_row, "", 1024, 1024))
    exit(EX_EOM);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2687 2688 2689 2690
  return 0;
} /* init_dumping */


2691 2692
my_bool include_table(byte* hash_key, uint len)
{
serg@serg.mylan's avatar
serg@serg.mylan committed
2693
  if (hash_search(&ignore_table, (byte*) hash_key, len))
2694 2695 2696 2697 2698
    return FALSE;

  return TRUE;
}

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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2700 2701 2702 2703
static int dump_all_tables_in_db(char *database)
{
  char *table;
  uint numrows;
2704
  char table_buff[NAME_LEN*2+3];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2705

2706 2707 2708 2709 2710 2711
  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
2712 2713
  if (init_dumping(database))
    return 1;
2714
  if (opt_xml)
2715
    print_xml_tag1(md_result_file, "", "database name=", database, "\n");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2716 2717 2718 2719
  if (lock_tables)
  {
    DYNAMIC_STRING query;
    init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
2720
    for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2721
    {
2722
      dynstr_append(&query, quote_name(table, table_buff, 1));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2723 2724 2725
      dynstr_append(&query, " READ /*!32311 LOCAL */,");
    }
    if (numrows && mysql_real_query(sock, query.str, query.length-1))
2726
      DB_error(sock, "when using LOCK TABLES");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2727 2728 2729 2730 2731 2732
            /* We shall continue here, if --force was given */
    dynstr_free(&query);
  }
  if (flush_logs)
  {
    if (mysql_refresh(sock, REFRESH_LOG))
2733
      DB_error(sock, "when doing refresh");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2734 2735
           /* We shall continue here, if --force was given */
  }
2736
  while ((table= getTableName(0)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2737
  {
2738 2739 2740
    char *end= strmov(afterdot, table);
    if (include_table(hash_key, end - hash_key))
    {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
2741
      dump_table(table,database);
2742 2743
      my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
      order_by= 0;
2744 2745 2746
      if (opt_dump_triggers && ! opt_xml &&
          mysql_get_server_version(sock) >= 50009)
        dump_triggers_for_table(table, database);
2747
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2748
  }
2749 2750 2751 2752 2753 2754
  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);
  }
2755
  if (opt_xml)
2756
  {
2757
    fputs("</database>\n", md_result_file);
2758 2759
    check_io(md_result_file);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2760
  if (lock_tables)
2761
    VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2762 2763 2764 2765
  return 0;
} /* dump_all_tables_in_db */


2766 2767 2768 2769 2770 2771
/*
   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
2772

2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783
  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];

2784 2785 2786 2787 2788 2789
  if (mysql_select_db(sock, database))
  {
    DB_error(sock, "when selecting the database");
    return 1;
  }

2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801
  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))
2802
      DB_error(sock, "when using LOCK TABLES");
2803 2804 2805 2806 2807 2808
            /* We shall continue here, if --force was given */
    dynstr_free(&query);
  }
  if (flush_logs)
  {
    if (mysql_refresh(sock, REFRESH_LOG))
2809
      DB_error(sock, "when doing refresh");
2810 2811 2812
           /* We shall continue here, if --force was given */
  }
  while ((table= getTableName(0)))
2813
     get_view_structure(table, database);
2814 2815 2816 2817 2818 2819
  if (opt_xml)
  {
    fputs("</database>\n", md_result_file);
    check_io(md_result_file);
  }
  if (lock_tables)
2820
    VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
2821 2822
  return 0;
} /* dump_all_tables_in_db */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2823

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

2825
/*
2826 2827 2828
  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
2829
  different case (e.g.  T1 vs t1)
2830

2831
  RETURN
ramil@mysql.com's avatar
ramil@mysql.com committed
2832 2833
    pointer to the table name
    0 if error
2834 2835
*/

ramil@mysql.com's avatar
ramil@mysql.com committed
2836
static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
2837
{
ramil@mysql.com's avatar
ramil@mysql.com committed
2838
  char *name= 0;
2839
  MYSQL_RES  *table_res;
2840
  MYSQL_ROW  row;
2841
  char query[50 + 2*NAME_LEN];
2842
  char show_name_buff[FN_REFLEN];
2843
  DBUG_ENTER("get_actual_table_name");
2844

2845 2846
  /* Check memory for quote_for_like() */
  DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
2847
  my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
2848
              quote_for_like(old_table_name, show_name_buff));
2849

2850 2851 2852 2853
  if (mysql_query_with_error_report(sock, 0, query))
  {
    safe_exit(EX_MYSQLERR);
  }
2854

2855
  if ((table_res= mysql_store_result(sock)))
2856
  {
2857 2858 2859
    my_ulonglong num_rows= mysql_num_rows(table_res);
    if (num_rows > 0)
    {
ramil@mysql.com's avatar
ramil@mysql.com committed
2860
      ulong *lengths;
2861 2862 2863 2864 2865
      /*
        Return first row
        TODO: Return all matching rows
      */
      row= mysql_fetch_row(table_res);
ramil@mysql.com's avatar
ramil@mysql.com committed
2866
      lengths= mysql_fetch_lengths(table_res);
ramil@mysql.com's avatar
ramil@mysql.com committed
2867
      name= strmake_root(root, row[0], lengths[0]);
2868 2869
    }
    mysql_free_result(table_res);
2870
  }
ramil@mysql.com's avatar
ramil@mysql.com committed
2871 2872
  DBUG_PRINT("exit", ("new_table_name: %s", name));
  DBUG_RETURN(name);
2873
}
2874

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2875 2876 2877

static int dump_selected_tables(char *db, char **table_names, int tables)
{
2878
  char table_buff[NAME_LEN*+3];
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2879
  DYNAMIC_STRING lock_tables_query;
ramil@mysql.com's avatar
ramil@mysql.com committed
2880 2881
  MEM_ROOT root;
  char **dump_tables, **pos, **end;
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2882
  DBUG_ENTER("dump_selected_tables");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2883 2884 2885

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

ramil@mysql.com's avatar
ramil@mysql.com committed
2887 2888 2889
  init_alloc_root(&root, 8192, 0);
  if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
     exit(EX_EOM);
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2890 2891 2892

  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
2893
  {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2894
    /* the table name passed on commandline may be wrong case */
ramil@mysql.com's avatar
ramil@mysql.com committed
2895
    if ((*pos= get_actual_table_name(*table_names, &root)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2896
    {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2897 2898 2899
      /* Add found table name to lock_tables_query */
      if (lock_tables)
      {
ramil@mysql.com's avatar
ramil@mysql.com committed
2900
        dynstr_append(&lock_tables_query, quote_name(*pos, table_buff, 1));
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2901 2902
        dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,");
      }
ramil@mysql.com's avatar
ramil@mysql.com committed
2903
      pos++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2904
    }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2905
    else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2906
    {
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2907 2908 2909 2910
       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
2911
    }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2912
  }
ramil@mysql.com's avatar
ramil@mysql.com committed
2913
  end= pos;
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2914 2915 2916 2917 2918

  if (lock_tables)
  {
    if (mysql_real_query(sock, lock_tables_query.str,
                         lock_tables_query.length-1))
2919
      DB_error(sock, "when doing LOCK TABLES");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2920 2921
       /* We shall countinue here, if --force was given */
  }
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2922
  dynstr_free(&lock_tables_query);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2923 2924 2925
  if (flush_logs)
  {
    if (mysql_refresh(sock, REFRESH_LOG))
2926
      DB_error(sock, "when doing refresh");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2927 2928
     /* We shall countinue here, if --force was given */
  }
2929
  if (opt_xml)
2930
    print_xml_tag1(md_result_file, "", "database name=", db, "\n");
2931

msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2932
  /* Dump each selected table */
ramil@mysql.com's avatar
ramil@mysql.com committed
2933
  for (pos= dump_tables; pos < end; pos++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2934
  {
ramil@mysql.com's avatar
ramil@mysql.com committed
2935 2936
    DBUG_PRINT("info",("Dumping table %s", *pos));
    dump_table(*pos, db);
2937 2938
    if (opt_dump_triggers &&
        mysql_get_server_version(sock) >= 50009)
ramil@mysql.com's avatar
ramil@mysql.com committed
2939
      dump_triggers_for_table(*pos, db);
2940
  }
2941 2942

  /* Dump each selected view */
2943
  if (seen_views)
2944
  {
ramil@mysql.com's avatar
ramil@mysql.com committed
2945 2946
    for (pos= dump_tables; pos < end; pos++)
      get_view_structure(*pos, db);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2947
  }
2948 2949 2950 2951 2952 2953 2954
  /* 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);
  }
ramil@mysql.com's avatar
ramil@mysql.com committed
2955
  free_root(&root, MYF(0));
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2956 2957
  my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
  order_by= 0;
2958
  if (opt_xml)
2959
  {
2960
    fputs("</database>\n", md_result_file);
2961 2962
    check_io(md_result_file);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2963
  if (lock_tables)
2964
    VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
msvensson@neptunus.(none)[msvensson]'s avatar
patch  
msvensson@neptunus.(none)[msvensson] committed
2965
  DBUG_RETURN(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2966 2967 2968
} /* dump_selected_tables */


2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985
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])
    {
2986
      /* SHOW MASTER STATUS reports file and position */
2987 2988 2989 2990 2991 2992
      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",
2993
              comment_prefix, row[0], row[1]);
2994 2995
      check_io(md_result_file);
    }
2996 2997 2998
    else if (!ignore_errors)
    {
      /* SHOW MASTER STATUS reports nothing and --force is not enabled */
2999 3000
      my_printf_error(0, "Error: Binlogging on server not active",
                      MYF(0));
3001 3002 3003
      mysql_free_result(master);
      return 1;
    }
3004 3005 3006 3007 3008 3009 3010 3011
    mysql_free_result(master);
  }
  return 0;
}


static int do_flush_tables_read_lock(MYSQL *mysql_con)
{
3012 3013 3014 3015 3016 3017 3018 3019
  /*
    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.
  */
3020
  return
3021 3022 3023
    ( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") ||
      mysql_query_with_error_report(mysql_con, 0,
                                    "FLUSH TABLES WITH READ LOCK") );
3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044
}


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).
3045 3046 3047 3048

    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).
3049 3050
  */
  return (mysql_query_with_error_report(mysql_con, 0,
3051 3052 3053
                                        "SET SESSION TRANSACTION ISOLATION "
                                        "LEVEL REPEATABLE READ") ||
          mysql_query_with_error_report(mysql_con, 0,
3054 3055 3056 3057 3058 3059
                                        consistent_read_now ?
                                        "START TRANSACTION "
                                        "WITH CONSISTENT SNAPSHOT" :
                                        "BEGIN"));
}

3060 3061

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

3069
  *err_pos= 0;                  /* No error yet */
3070
  while (end > x && my_isspace(charset_info, end[-1]))
3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101
    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
3102 3103
/* Print a value with a prefix on file */
static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
3104 3105
                        const char *prefix, const char *name,
                        int string_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3106
{
3107
  MYSQL_FIELD   *field;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3108 3109 3110 3111 3112 3113 3114 3115
  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 */
      {
3116 3117 3118 3119 3120 3121 3122 3123
        fputc(' ',file);
        fputs(prefix, file);
        if (string_value)
          unescape(file,row[0],(uint) strlen(row[0]));
        else
          fputs(row[0], file);
        check_io(file);
        return;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3124 3125 3126
      }
    }
  }
3127
  return;                                       /* This shouldn't happen */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3128 3129 3130
} /* print_value */


3131 3132 3133
/*

  SYNOPSIS
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3134 3135 3136 3137

  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
3138 3139
  should not be ignored. If the user has selected to use INSERT DELAYED, it
  sets the value of the bool pointer supports_delayed_inserts to 0 if not
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3140 3141 3142 3143
  supported, 1 if it is supported.

  ARGS

3144
    check_if_ignore_table()
3145
    table_name                  Table name to check
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3146
    table_type                  Type of table
3147 3148

  GLOBAL VARIABLES
3149 3150
    sock                        MySQL socket
    verbose                     Write warning messages
3151 3152

  RETURN
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3153
    char (bit value)            See IGNORE_ values at top
3154 3155
*/

patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3156
char check_if_ignore_table(const char *table_name, char *table_type)
3157
{
3158
  char result= IGNORE_NONE;
3159 3160 3161
  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
3162
  DBUG_ENTER("check_if_ignore_table");
3163

3164 3165 3166
  /* 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",
3167
              quote_for_like(table_name, show_name_buff));
3168
  if (mysql_query_with_error_report(sock, &res, buff))
3169 3170
  {
    if (mysql_errno(sock) != ER_PARSE_ERROR)
3171
    {                                   /* If old MySQL version */
3172
      if (verbose)
3173 3174 3175
        fprintf(stderr,
                "-- Warning: Couldn't get status information for table %s (%s)\n",
                table_name,mysql_error(sock));
3176
      DBUG_RETURN(result);                       /* assume table is ok */
3177 3178
    }
  }
3179
  if (!(row= mysql_fetch_row(res)))
3180 3181
  {
    fprintf(stderr,
3182 3183
            "Error: Couldn't read status information for table %s (%s)\n",
            table_name, mysql_error(sock));
3184
    mysql_free_result(res);
3185
    DBUG_RETURN(result);                         /* assume table is ok */
3186
  }
3187
  if (!(row[1]))
monty@mysql.com's avatar
monty@mysql.com committed
3188
    strmake(table_type, "VIEW", NAME_LEN-1);
3189 3190
  else
  {
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3191 3192 3193 3194 3195 3196
    /*
      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
    */
3197
    strmake(table_type, row[1], NAME_LEN-1);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213
    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;
3214
  }
3215
  mysql_free_result(res);
patg@krsna.patg.net's avatar
patg@krsna.patg.net committed
3216
  DBUG_RETURN(result);
3217 3218
}

3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235
/*
  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
3236

3237 3238 3239 3240 3241 3242
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
3243
  uint result_length = 0;
3244 3245
  char *result = 0;

3246 3247
  my_snprintf(show_keys_buff, sizeof(show_keys_buff),
              "SHOW KEYS FROM %s", table_name);
3248 3249 3250 3251 3252 3253 3254 3255 3256 3257
  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
3258 3259 3260 3261 3262 3263 3264
  /*
   * 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)
3265
  {
tsmith@build.mysql.com's avatar
tsmith@build.mysql.com committed
3266 3267 3268 3269
    /* Key is unique */
    do
      result_length += strlen(row[4]) + 1;      /* + 1 for ',' or \0 */
    while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1);
3270 3271 3272
  }

  /* Build the ORDER BY clause result */
monty@mishka.local's avatar
monty@mishka.local committed
3273 3274
  if (result_length)
  {
3275 3276 3277
    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
3278 3279
    if (!result)
    {
3280 3281 3282
      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
3283
    mysql_data_seek(res, 0);
3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296
    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;
}

3297

3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317
/*
  Replace a substring

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

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

static int replace(DYNAMIC_STRING *ds_str,
                   const char *search_str, ulong search_len,
                   const char *replace_str, ulong replace_len)
{
msvensson@neptunus.(none)'s avatar
msvensson@neptunus.(none) committed
3318
  DYNAMIC_STRING ds_tmp;
3319 3320 3321 3322
  const char *start= strstr(ds_str->str, search_str);
  if (!start)
    return 1;
  init_dynamic_string(&ds_tmp, "",
3323
                      ds_str->length + replace_len, 256);
3324 3325 3326 3327 3328 3329 3330 3331 3332
  dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
  dynstr_append_mem(&ds_tmp, replace_str, replace_len);
  dynstr_append(&ds_tmp, start + search_len);
  dynstr_set(ds_str, ds_tmp.str);
  dynstr_free(&ds_tmp);
  return 0;
}


3333 3334 3335 3336
/*
  Getting VIEW structure

  SYNOPSIS
3337
    get_view_structure()
3338 3339 3340 3341 3342 3343 3344 3345
    table   view name
    db      db name

  RETURN
    0 OK
    1 ERROR
*/

3346
static my_bool get_view_structure(char *table, char* db)
3347
{
3348
  MYSQL_RES  *table_res;
3349 3350
  MYSQL_ROW  row;
  MYSQL_FIELD *field;
3351 3352 3353
  char       *result_table, *opt_quoted_table;
  char       table_buff[NAME_LEN*2+3];
  char       table_buff2[NAME_LEN*2+3];
3354
  char       query[QUERY_LENGTH];
3355
  FILE       *sql_file = md_result_file;
3356
  DBUG_ENTER("get_view_structure");
3357

3358
  if (tFlag) /* Don't write table creation info */
3359 3360 3361 3362 3363
    DBUG_RETURN(0);

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

jimw@mysql.com's avatar
jimw@mysql.com committed
3364
#ifdef NOT_REALLY_USED_YET
3365
  sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
3366
          (opt_quoted || opt_keywords));
jimw@mysql.com's avatar
jimw@mysql.com committed
3367 3368
#endif

3369 3370 3371
  result_table=     quote_name(table, table_buff, 1);
  opt_quoted_table= quote_name(table, table_buff2, 0);

3372
  my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %s", result_table);
3373
  if (mysql_query_with_error_report(sock, &table_res, query))
3374 3375 3376 3377 3378
  {
    safe_exit(EX_MYSQLERR);
    DBUG_RETURN(0);
  }

3379 3380 3381 3382 3383 3384 3385 3386 3387 3388
  /* Check if this is a view */
  field= mysql_fetch_field_direct(table_res, 0);
  if (strcmp(field->name, "View") != 0)
  {
    if (verbose)
      fprintf(stderr, "-- It's base table, skipped\n");
    DBUG_RETURN(0);
  }

  /* If requested, open separate .sql file for this view */
3389 3390
  if (path)
  {
3391
    if (!(sql_file= open_sql_file_for_table(table)))
3392 3393 3394 3395 3396 3397 3398 3399 3400
    {
      safe_exit(EX_MYSQLERR);
      DBUG_RETURN(1);
    }
    write_header(sql_file, db);
  }

  if (!opt_xml && opt_comments)
  {
3401
    fprintf(sql_file, "\n--\n-- Final view structure for view %s\n--\n\n",
3402 3403 3404 3405 3406
            result_table);
    check_io(sql_file);
  }
  if (opt_drop)
  {
3407 3408 3409 3410
    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);
3411 3412 3413 3414
    check_io(sql_file);
  }


3415 3416 3417 3418
  my_snprintf(query, sizeof(query),
              "SELECT CHECK_OPTION, DEFINER, SECURITY_TYPE "            \
              "FROM information_schema.views "                          \
              "WHERE table_name=\"%s\" AND table_schema=\"%s\"", table, db);
3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444
  if (mysql_query(sock, query))
  {
    /*
      Use the raw output from SHOW CREATE TABLE if
       information_schema query fails.
     */
    row= mysql_fetch_row(table_res);
    fprintf(sql_file, "/*!50001 %s */;\n", row[1]);
    check_io(sql_file);
    mysql_free_result(table_res);
  }
  else
  {
    char *ptr;
    ulong *lengths;
    char search_buf[256], replace_buf[256];
    ulong search_len, replace_len;
    DYNAMIC_STRING ds_view;

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

    /* Get the result from "select ... information_schema" */
3445 3446
    if (!(table_res= mysql_store_result(sock)) ||
        !(row= mysql_fetch_row(table_res)))
3447 3448 3449 3450
    {
      safe_exit(EX_MYSQLERR);
      DBUG_RETURN(1);
    }
3451

3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482
    lengths= mysql_fetch_lengths(table_res);

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

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

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

      parse_user(row[1], lengths[1], user_name_str, &user_name_len,
3483
                 host_name_str, &host_name_len);
3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510

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

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

  /* If a separate .sql file was opened, close it now */
3511 3512 3513 3514 3515 3516 3517 3518 3519 3520
  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
3521 3522
int main(int argc, char **argv)
{
3523 3524
  MY_INIT("mysqldump");

3525
  compatible_mode_normal_str[0]= 0;
3526
  default_charset= (char *)mysql_universal_client_charset;
monty@mishka.local's avatar
monty@mishka.local committed
3527
  bzero((char*) &ignore_table, sizeof(ignore_table));
3528

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3529 3530 3531 3532 3533
  if (get_options(&argc, &argv))
  {
    my_end(0);
    exit(EX_USAGE);
  }
3534
  if (dbConnect(current_host, current_user, opt_password))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3535 3536
    exit(EX_MYSQLERR);
  if (!path)
3537 3538
    write_header(md_result_file, *argv);

3539 3540 3541 3542 3543 3544 3545 3546
  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)
3547
  {
3548 3549 3550
    if (flush_logs && mysql_refresh(sock, REFRESH_LOG))
      goto err;
    flush_logs= 0; /* not anymore; that would not be sensible */
3551
  }
3552 3553
  if (opt_master_data && do_show_master_status(sock))
    goto err;
3554
  if (opt_single_transaction && do_unlock_tables(sock)) /* unlock but no commit! */
3555 3556
    goto err;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3557 3558 3559
  if (opt_alldbs)
    dump_all_databases();
  else if (argc > 1 && !opt_databases)
3560 3561
  {
    /* Only one database and selected table(s) */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3562
    dump_selected_tables(*argv, (argv + 1), (argc - 1));
3563
  }
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
3564
  else
3565 3566
  {
    /* One or more databases, all tables */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3567
    dump_databases(argv);
3568
  }
3569 3570 3571
#ifdef HAVE_SMEM
  my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif
3572 3573 3574 3575 3576 3577 3578
  /*
    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
3579
  dbDisconnect(current_host);
3580 3581
  if (!path)
    write_footer(md_result_file);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
3582 3583
  if (md_result_file != stdout)
    my_fclose(md_result_file, MYF(0));
3584
  my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
monty@mishka.local's avatar
monty@mishka.local committed
3585 3586
  if (hash_inited(&ignore_table))
    hash_free(&ignore_table);
3587
  if (extended_insert)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3588
    dynstr_free(&extended_row);
3589 3590
  if (insert_pat_inited)
    dynstr_free(&insert_pat);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3591 3592 3593
  my_end(0);
  return(first_error);
} /* main */