00001 /* Copyright (C) 2000 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /* mysqldump.c - Dump a tables contents and format to an ASCII file 00018 ** 00019 ** The author's original notes follow :- 00020 ** 00021 ** AUTHOR: Igor Romanenko (igor@frog.kiev.ua) 00022 ** DATE: December 3, 1994 00023 ** WARRANTY: None, expressed, impressed, implied 00024 ** or other 00025 ** STATUS: Public domain 00026 ** Adapted and optimized for MySQL by 00027 ** Michael Widenius, Sinisa Milivojevic, Jani Tolonen 00028 ** -w --where added 9/10/98 by Jim Faucette 00029 ** slave code by David Saez Padros <david@ols.es> 00030 ** master/autocommit code by Brian Aker <brian@tangent.org> 00031 ** SSL by 00032 ** Andrei Errapart <andreie@no.spam.ee> 00033 ** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee> 00034 ** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up 00035 ** and adapted to mysqldump 05/11/01 by Jani Tolonen 00036 ** Added --single-transaction option 06/06/2002 by Peter Zaitsev 00037 ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov 00038 */ 00039 00040 #define DUMP_VERSION "10.10" 00041 00042 #include <my_global.h> 00043 #include <my_sys.h> 00044 #include <my_user.h> 00045 #include <m_string.h> 00046 #include <m_ctype.h> 00047 #include <hash.h> 00048 00049 #include "client_priv.h" 00050 #include "mysql.h" 00051 #include "mysql_version.h" 00052 #include "mysqld_error.h" 00053 #include "../sql/ha_ndbcluster_tables.h" 00054 00055 /* Exit codes */ 00056 00057 #define EX_USAGE 1 00058 #define EX_MYSQLERR 2 00059 #define EX_CONSCHECK 3 00060 #define EX_EOM 4 00061 #define EX_EOF 5 /* ferror for output file was got */ 00062 #define EX_ILLEGAL_TABLE 6 00063 00064 /* index into 'show fields from table' */ 00065 00066 #define SHOW_FIELDNAME 0 00067 #define SHOW_TYPE 1 00068 #define SHOW_NULL 2 00069 #define SHOW_DEFAULT 4 00070 #define SHOW_EXTRA 5 00071 00072 /* Size of buffer for dump's select query */ 00073 #define QUERY_LENGTH 1536 00074 00075 /* ignore table flags */ 00076 #define IGNORE_NONE 0x00 /* no ignore */ 00077 #define IGNORE_DATA 0x01 /* don't dump data for this table */ 00078 #define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */ 00079 00080 static char *add_load_option(char *ptr, const char *object, 00081 const char *statement); 00082 static ulong find_set(TYPELIB *lib, const char *x, uint length, 00083 char **err_pos, uint *err_len); 00084 static char *alloc_query_str(ulong size); 00085 00086 static char *field_escape(char *to,const char *from,uint length); 00087 static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, 00088 quick= 1, extended_insert= 1, 00089 lock_tables=1,ignore_errors=0,flush_logs=0, 00090 opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0, 00091 opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0, 00092 opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0, 00093 opt_set_charset=0, 00094 opt_autocommit=0,opt_disable_keys=1,opt_xml=0, 00095 opt_delete_master_logs=0, tty_password=0, 00096 opt_single_transaction=0, opt_comments= 0, opt_compact= 0, 00097 opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0, 00098 opt_complete_insert= 0, opt_drop_database= 0, 00099 opt_replace_into= 0, 00100 opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1, 00101 opt_events= 0, 00102 opt_alltspcs=0; 00103 static ulong opt_max_allowed_packet, opt_net_buffer_length; 00104 static MYSQL mysql_connection,*mysql=0; 00105 static my_bool insert_pat_inited=0; 00106 static DYNAMIC_STRING insert_pat; 00107 static char *opt_password=0,*current_user=0, 00108 *current_host=0,*path=0,*fields_terminated=0, 00109 *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0, 00110 *where=0, *order_by=0, 00111 *opt_compatible_mode_str= 0, 00112 *err_ptr= 0; 00113 static char compatible_mode_normal_str[255]; 00114 static ulong opt_compatible_mode= 0; 00115 #define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1 00116 #define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2 00117 static uint opt_mysql_port= 0, err_len= 0, opt_master_data; 00118 static my_string opt_mysql_unix_port=0; 00119 static int first_error=0; 00120 static DYNAMIC_STRING extended_row; 00121 #include <sslopt-vars.h> 00122 FILE *md_result_file; 00123 #ifdef HAVE_SMEM 00124 static char *shared_memory_base_name=0; 00125 #endif 00126 static uint opt_protocol= 0; 00127 /* 00128 Constant for detection of default value of default_charset. 00129 If default_charset is equal to mysql_universal_client_charset, then 00130 it is the default value which assigned at the very beginning of main(). 00131 */ 00132 static const char *mysql_universal_client_charset= 00133 MYSQL_UNIVERSAL_CLIENT_CHARSET; 00134 static char *default_charset; 00135 static CHARSET_INFO *charset_info= &my_charset_latin1; 00136 const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace"; 00137 /* have we seen any VIEWs during table scanning? */ 00138 my_bool seen_views= 0; 00139 const char *compatible_mode_names[]= 00140 { 00141 "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2", 00142 "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", 00143 "ANSI", 00144 NullS 00145 }; 00146 #define MASK_ANSI_QUOTES \ 00147 (\ 00148 (1<<2) | /* POSTGRESQL */\ 00149 (1<<3) | /* ORACLE */\ 00150 (1<<4) | /* MSSQL */\ 00151 (1<<5) | /* DB2 */\ 00152 (1<<6) | /* MAXDB */\ 00153 (1<<10) /* ANSI */\ 00154 ) 00155 TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1, 00156 "", compatible_mode_names, NULL}; 00157 00158 HASH ignore_table; 00159 00160 static struct my_option my_long_options[] = 00161 { 00162 {"all", 'a', "Deprecated. Use --create-options instead.", 00163 (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1, 00164 0, 0, 0, 0, 0}, 00165 {"all-databases", 'A', 00166 "Dump all the databases. This will be same as --databases with all databases selected.", 00167 (gptr*) &opt_alldbs, (gptr*) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 00168 0, 0}, 00169 {"all-tablespaces", 'Y', 00170 "Dump all the tablespaces.", 00171 (gptr*) &opt_alltspcs, (gptr*) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 00172 0, 0}, 00173 {"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.", 00174 (gptr*) &opt_drop_database, (gptr*) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 00175 0}, 00176 {"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.", 00177 (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 00178 0}, 00179 {"add-locks", OPT_LOCKS, "Add locks around insert statements.", 00180 (gptr*) &opt_lock, (gptr*) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 00181 0}, 00182 {"allow-keywords", OPT_KEYWORDS, 00183 "Allow creation of column names that are keywords.", (gptr*) &opt_keywords, 00184 (gptr*) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00185 #ifdef __NETWARE__ 00186 {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 00187 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 00188 #endif 00189 {"character-sets-dir", OPT_CHARSETS_DIR, 00190 "Directory where character sets are.", (gptr*) &charsets_dir, 00191 (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00192 {"comments", 'i', "Write additional information.", 00193 (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG, 00194 1, 0, 0, 0, 0, 0}, 00195 {"compatible", OPT_COMPATIBLE, 00196 "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.", 00197 (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0, 00198 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00199 {"compact", OPT_COMPACT, 00200 "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", 00201 (gptr*) &opt_compact, (gptr*) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 00202 0, 0}, 00203 {"complete-insert", 'c', "Use complete insert statements.", 00204 (gptr*) &opt_complete_insert, (gptr*) &opt_complete_insert, 0, GET_BOOL, 00205 NO_ARG, 0, 0, 0, 0, 0, 0}, 00206 {"compress", 'C', "Use compression in server/client protocol.", 00207 (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 00208 0, 0, 0}, 00209 {"create-options", OPT_CREATE_OPTIONS, 00210 "Include all MySQL specific create options.", 00211 (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1, 00212 0, 0, 0, 0, 0}, 00213 {"databases", 'B', 00214 "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.", 00215 (gptr*) &opt_databases, (gptr*) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, 00216 0, 0, 0, 0}, 00217 #ifdef DBUG_OFF 00218 {"debug", '#', "This is a non-debug version. Catch this and exit", 00219 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, 00220 #else 00221 {"debug", '#', "Output debug log", (gptr*) &default_dbug_option, 00222 (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 00223 #endif 00224 {"default-character-set", OPT_DEFAULT_CHARSET, 00225 "Set the default character set.", (gptr*) &default_charset, 00226 (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00227 {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ", 00228 (gptr*) &opt_delayed, (gptr*) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 00229 0, 0}, 00230 {"delete-master-logs", OPT_DELETE_MASTER_LOGS, 00231 "Delete logs on master after backup. This automatically enables --master-data.", 00232 (gptr*) &opt_delete_master_logs, (gptr*) &opt_delete_master_logs, 0, 00233 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00234 {"disable-keys", 'K', 00235 "'/*!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, 00236 (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, 00237 {"events", 'E', "Dump events.", 00238 (gptr*) &opt_events, (gptr*) &opt_events, 0, GET_BOOL, 00239 NO_ARG, 0, 0, 0, 0, 0, 0}, 00240 {"extended-insert", 'e', 00241 "Allows utilization of the new, much faster INSERT syntax.", 00242 (gptr*) &extended_insert, (gptr*) &extended_insert, 0, GET_BOOL, NO_ARG, 00243 1, 0, 0, 0, 0, 0}, 00244 {"fields-terminated-by", OPT_FTB, 00245 "Fields in the textfile are terminated by ...", (gptr*) &fields_terminated, 00246 (gptr*) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00247 {"fields-enclosed-by", OPT_ENC, 00248 "Fields in the importfile are enclosed by ...", (gptr*) &enclosed, 00249 (gptr*) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, 00250 {"fields-optionally-enclosed-by", OPT_O_ENC, 00251 "Fields in the i.file are opt. enclosed by ...", (gptr*) &opt_enclosed, 00252 (gptr*) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, 00253 {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...", 00254 (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00255 {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.", 00256 (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, 00257 0, 0, 0, 0, 0, 0}, 00258 {"flush-logs", 'F', "Flush logs file in server before starting dump. " 00259 "Note that if you dump many databases at once (using the option " 00260 "--databases= or --all-databases), the logs will be flushed for " 00261 "each database dumped. The exception is when using --lock-all-tables " 00262 "or --master-data: " 00263 "in this case the logs will be flushed only once, corresponding " 00264 "to the moment all tables are locked. So if you want your dump and " 00265 "the log flush to happen at the same exact moment you should use " 00266 "--lock-all-tables or --master-data with --flush-logs", 00267 (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 00268 0, 0}, 00269 {"force", 'f', "Continue even if we get an sql-error.", 00270 (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG, 00271 0, 0, 0, 0, 0, 0}, 00272 {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, 00273 NO_ARG, 0, 0, 0, 0, 0, 0}, 00274 {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, " 00275 "VARBINARY, BLOB) in hexadecimal format.", 00276 (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00277 {"host", 'h', "Connect to host.", (gptr*) ¤t_host, 00278 (gptr*) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00279 {"ignore-table", OPT_IGNORE_TABLE, 00280 "Do not dump the specified table. To specify more than one table to ignore, " 00281 "use the directive multiple times, once for each table. Each table must " 00282 "be specified with both database and table names, e.g. --ignore-table=database.table", 00283 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00284 {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.", 00285 (gptr*) &opt_ignore, (gptr*) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 00286 0, 0}, 00287 {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...", 00288 (gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR, 00289 REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00290 {"lock-all-tables", 'x', "Locks all tables across all databases. This " 00291 "is achieved by taking a global read lock for the duration of the whole " 00292 "dump. Automatically turns --single-transaction and --lock-tables off.", 00293 (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, 00294 0, 0, 0, 0, 0, 0}, 00295 {"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables, 00296 (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, 00297 {"master-data", OPT_MASTER_DATA, 00298 "This causes the binary log position and filename to be appended to the " 00299 "output. If equal to 1, will print it as a CHANGE MASTER command; if equal" 00300 " to 2, that command will be prefixed with a comment symbol. " 00301 "This option will turn --lock-all-tables on, unless " 00302 "--single-transaction is specified too (in which case a " 00303 "global read lock is only taken a short time at the beginning of the dump " 00304 "- don't forget to read about --single-transaction below). In all cases " 00305 "any action on logs will happen at the exact moment of the dump." 00306 "Option automatically turns --lock-tables off.", 00307 (gptr*) &opt_master_data, (gptr*) &opt_master_data, 0, 00308 GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0}, 00309 {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "", 00310 (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0, 00311 GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096, 00312 (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0}, 00313 {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "", 00314 (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0, 00315 GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L, 00316 MALLOC_OVERHEAD-1024, 1024, 0}, 00317 {"no-autocommit", OPT_AUTOCOMMIT, 00318 "Wrap tables with autocommit/commit statements.", 00319 (gptr*) &opt_autocommit, (gptr*) &opt_autocommit, 0, GET_BOOL, NO_ARG, 00320 0, 0, 0, 0, 0, 0}, 00321 {"no-create-db", 'n', 00322 "'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.}.", 00323 (gptr*) &opt_create_db, (gptr*) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0, 00324 0, 0, 0, 0}, 00325 {"no-create-info", 't', "Don't write table creation info.", 00326 (gptr*) &opt_no_create_info, (gptr*) &opt_no_create_info, 0, GET_BOOL, 00327 NO_ARG, 0, 0, 0, 0, 0, 0}, 00328 {"no-data", 'd', "No row information.", (gptr*) &opt_no_data, 00329 (gptr*) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00330 {"no-set-names", 'N', 00331 "Deprecated. Use --skip-set-charset instead.", 00332 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 00333 {"opt", OPT_OPTIMIZE, 00334 "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.", 00335 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 00336 {"order-by-primary", OPT_ORDER_BY_PRIMARY, 00337 "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.", 00338 (gptr*) &opt_order_by_primary, (gptr*) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00339 {"password", 'p', 00340 "Password to use when connecting to server. If password is not given it's solicited on the tty.", 00341 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 00342 #ifdef __WIN__ 00343 {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, 00344 NO_ARG, 0, 0, 0, 0, 0, 0}, 00345 #endif 00346 {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, 00347 (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 00348 0}, 00349 {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 00350 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00351 {"quick", 'q', "Don't buffer query, dump directly to stdout.", 00352 (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, 00353 {"quote-names",'Q', "Quote table and column names with backticks (`).", 00354 (gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 00355 0, 0}, 00356 {"replace", OPT_MYSQL_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.", 00357 (gptr*) &opt_replace_into, (gptr*) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 00358 0, 0}, 00359 {"result-file", 'r', 00360 "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).", 00361 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00362 {"routines", 'R', "Dump stored routines (functions and procedures).", 00363 (gptr*) &opt_routines, (gptr*) &opt_routines, 0, GET_BOOL, 00364 NO_ARG, 0, 0, 0, 0, 0, 0}, 00365 {"set-charset", OPT_SET_CHARSET, 00366 "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.", 00367 (gptr*) &opt_set_charset, (gptr*) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1, 00368 0, 0, 0, 0, 0}, 00369 {"set-variable", 'O', 00370 "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", 00371 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00372 #ifdef HAVE_SMEM 00373 {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, 00374 "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 00375 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00376 #endif 00377 /* 00378 Note that the combination --single-transaction --master-data 00379 will give bullet-proof binlog position only if server >=4.1.3. That's the 00380 old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug. 00381 */ 00382 {"single-transaction", OPT_TRANSACTION, 00383 "Creates a consistent snapshot by dumping all tables in a single " 00384 "transaction. Works ONLY for tables stored in storage engines which " 00385 "support multiversioning (currently only InnoDB does); the dump is NOT " 00386 "guaranteed to be consistent for other storage engines. Option " 00387 "automatically turns off --lock-tables.", 00388 (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0, 00389 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00390 {"skip-opt", OPT_SKIP_OPTIMIZATION, 00391 "Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.", 00392 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 00393 {"socket", 'S', "Socket file to use for connection.", 00394 (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, 00395 REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00396 #include <sslopt-longopts.h> 00397 {"tab",'T', 00398 "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.", 00399 (gptr*) &path, (gptr*) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00400 {"tables", OPT_TABLES, "Overrides option --databases (-B).", 00401 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 00402 {"triggers", OPT_TRIGGERS, "Dump triggers for each dumped table", 00403 (gptr*) &opt_dump_triggers, (gptr*) &opt_dump_triggers, 0, GET_BOOL, 00404 NO_ARG, 1, 0, 0, 0, 0, 0}, 00405 {"tz-utc", OPT_TZ_UTC, 00406 "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.", 00407 (gptr*) &opt_tz_utc, (gptr*) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, 00408 #ifndef DONT_ALLOW_USER_CHANGE 00409 {"user", 'u', "User for login if not current user.", 00410 (gptr*) ¤t_user, (gptr*) ¤t_user, 0, GET_STR, REQUIRED_ARG, 00411 0, 0, 0, 0, 0, 0}, 00412 #endif 00413 {"verbose", 'v', "Print info about the various stages.", 00414 (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 00415 {"version",'V', "Output version information and exit.", 0, 0, 0, 00416 GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 00417 {"where", 'w', "Dump only selected records; QUOTES mandatory!", 00418 (gptr*) &where, (gptr*) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 00419 {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG, 00420 NO_ARG, 0, 0, 0, 0, 0, 0}, 00421 {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} 00422 }; 00423 00424 static const char *load_default_groups[]= { "mysqldump","client",0 }; 00425 00426 static void safe_exit(int error); 00427 static void write_header(FILE *sql_file, char *db_name); 00428 static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, 00429 const char *prefix,const char *name, 00430 int string_value); 00431 static int dump_selected_tables(char *db, char **table_names, int tables); 00432 static int dump_all_tables_in_db(char *db); 00433 static int init_dumping(char *); 00434 static int dump_databases(char **); 00435 static int dump_all_databases(); 00436 static char *quote_name(const char *name, char *buff, my_bool force); 00437 char check_if_ignore_table(const char *table_name, char *table_type); 00438 static char *primary_key_fields(const char *table_name); 00439 static my_bool get_view_structure(char *table, char* db); 00440 static my_bool dump_all_views_in_db(char *database); 00441 00442 #include <help_start.h> 00443 00444 /* 00445 Print the supplied message if in verbose mode 00446 00447 SYNOPSIS 00448 verbose_msg() 00449 fmt format specifier 00450 ... variable number of parameters 00451 */ 00452 00453 static void verbose_msg(const char *fmt, ...) 00454 { 00455 va_list args; 00456 DBUG_ENTER("verbose_msg"); 00457 00458 if (!verbose) 00459 DBUG_VOID_RETURN; 00460 00461 va_start(args, fmt); 00462 vfprintf(stderr, fmt, args); 00463 va_end(args); 00464 00465 DBUG_VOID_RETURN; 00466 } 00467 00468 /* 00469 exit with message if ferror(file) 00470 00471 SYNOPSIS 00472 check_io() 00473 file - checked file 00474 */ 00475 00476 void check_io(FILE *file) 00477 { 00478 if (ferror(file)) 00479 { 00480 fprintf(stderr, "%s: Got errno %d on write\n", my_progname, errno); 00481 ignore_errors= 0; /* We can't ignore this error */ 00482 safe_exit(EX_EOF); 00483 } 00484 } 00485 00486 static void print_version(void) 00487 { 00488 printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION, 00489 MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); 00490 NETWARE_SET_SCREEN_MODE(1); 00491 } /* print_version */ 00492 00493 00494 static void short_usage_sub(void) 00495 { 00496 printf("Usage: %s [OPTIONS] database [tables]\n", my_progname); 00497 printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n", 00498 my_progname); 00499 printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname); 00500 NETWARE_SET_SCREEN_MODE(1); 00501 } 00502 00503 00504 static void usage(void) 00505 { 00506 print_version(); 00507 puts("By Igor Romanenko, Monty, Jani & Sinisa"); 00508 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"); 00509 puts("Dumping definition and data mysql database or table"); 00510 short_usage_sub(); 00511 print_defaults("my",load_default_groups); 00512 my_print_help(my_long_options); 00513 my_print_variables(my_long_options); 00514 } /* usage */ 00515 00516 00517 static void short_usage(void) 00518 { 00519 short_usage_sub(); 00520 printf("For more options, use %s --help\n", my_progname); 00521 } 00522 00523 #include <help_end.h> 00524 00525 00526 static void write_header(FILE *sql_file, char *db_name) 00527 { 00528 if (opt_xml) 00529 { 00530 fputs("<?xml version=\"1.0\"?>\n", sql_file); 00531 fputs("<mysqldump ", sql_file); 00532 fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", 00533 sql_file); 00534 fputs(">\n", sql_file); 00535 check_io(sql_file); 00536 } 00537 else if (!opt_compact) 00538 { 00539 if (opt_comments) 00540 { 00541 fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION); 00542 fprintf(sql_file, "-- Host: %s Database: %s\n", 00543 current_host ? current_host : "localhost", db_name ? db_name : 00544 ""); 00545 fputs("-- ------------------------------------------------------\n", 00546 sql_file); 00547 fprintf(sql_file, "-- Server version\t%s\n", 00548 mysql_get_server_info(&mysql_connection)); 00549 } 00550 if (opt_set_charset) 00551 fprintf(sql_file, 00552 "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;" 00553 "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;" 00554 "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;" 00555 "\n/*!40101 SET NAMES %s */;\n",default_charset); 00556 00557 if (opt_tz_utc) 00558 { 00559 fprintf(sql_file, "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n"); 00560 fprintf(sql_file, "/*!40103 SET TIME_ZONE='+00:00' */;\n"); 00561 } 00562 00563 if (!path) 00564 { 00565 fprintf(md_result_file,"\;\n\;\n\ 00568 "); 00569 } 00570 fprintf(sql_file, 00571 "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='%s%s%s' */;\n" 00572 "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n", 00573 path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",", 00574 compatible_mode_normal_str); 00575 check_io(sql_file); 00576 } 00577 } /* write_header */ 00578 00579 00580 static void write_footer(FILE *sql_file) 00581 { 00582 if (opt_xml) 00583 { 00584 fputs("</mysqldump>\n", sql_file); 00585 check_io(sql_file); 00586 } 00587 else if (!opt_compact) 00588 { 00589 if (opt_tz_utc) 00590 fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n"); 00591 00592 fprintf(sql_file,"\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n"); 00593 if (!path) 00594 { 00595 fprintf(md_result_file,"\;\n\;\n"); 00598 } 00599 if (opt_set_charset) 00600 fprintf(sql_file, 00601 "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n" 00602 "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n" 00603 "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n"); 00604 fprintf(sql_file, 00605 "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n"); 00606 fputs("\n", sql_file); 00607 if (opt_comments) 00608 { 00609 char time_str[20]; 00610 get_date(time_str, GETDATE_DATE_TIME, 0); 00611 fprintf(sql_file, "-- Dump completed on %s\n", 00612 time_str); 00613 } 00614 check_io(sql_file); 00615 } 00616 } /* write_footer */ 00617 00618 static void free_table_ent(char *key) 00619 00620 { 00621 my_free((gptr) key, MYF(0)); 00622 } 00623 00624 00625 byte* get_table_key(const char *entry, uint *length, 00626 my_bool not_used __attribute__((unused))) 00627 { 00628 *length= strlen(entry); 00629 return (byte*) entry; 00630 } 00631 00632 00633 void init_table_rule_hash(HASH* h) 00634 { 00635 if (hash_init(h, charset_info, 16, 0, 0, 00636 (hash_get_key) get_table_key, 00637 (hash_free_key) free_table_ent, 0)) 00638 exit(EX_EOM); 00639 } 00640 00641 static my_bool 00642 get_one_option(int optid, const struct my_option *opt __attribute__((unused)), 00643 char *argument) 00644 { 00645 switch (optid) { 00646 #ifdef __NETWARE__ 00647 case OPT_AUTO_CLOSE: 00648 setscreenmode(SCR_AUTOCLOSE_ON_EXIT); 00649 break; 00650 #endif 00651 case 'p': 00652 if (argument) 00653 { 00654 char *start=argument; 00655 my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); 00656 opt_password=my_strdup(argument,MYF(MY_FAE)); 00657 while (*argument) *argument++= 'x'; /* Destroy argument */ 00658 if (*start) 00659 start[1]=0; /* Cut length of argument */ 00660 tty_password= 0; 00661 } 00662 else 00663 tty_password=1; 00664 break; 00665 case 'r': 00666 if (!(md_result_file = my_fopen(argument, O_WRONLY | FILE_BINARY, 00667 MYF(MY_WME)))) 00668 exit(1); 00669 break; 00670 case 'W': 00671 #ifdef __WIN__ 00672 opt_protocol = MYSQL_PROTOCOL_PIPE; 00673 #endif 00674 break; 00675 case 'N': 00676 opt_set_charset= 0; 00677 break; 00678 case 'T': 00679 opt_disable_keys=0; 00680 break; 00681 case '#': 00682 DBUG_PUSH(argument ? argument : default_dbug_option); 00683 break; 00684 #include <sslopt-case.h> 00685 case 'V': print_version(); exit(0); 00686 case 'X': 00687 opt_xml = 1; 00688 extended_insert= opt_drop= opt_lock= 00689 opt_disable_keys= opt_autocommit= opt_create_db= 0; 00690 break; 00691 case 'I': 00692 case '?': 00693 usage(); 00694 exit(0); 00695 case (int) OPT_MASTER_DATA: 00696 if (!argument) /* work like in old versions */ 00697 opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL; 00698 break; 00699 case (int) OPT_OPTIMIZE: 00700 extended_insert= opt_drop= opt_lock= quick= create_options= 00701 opt_disable_keys= lock_tables= opt_set_charset= 1; 00702 break; 00703 case (int) OPT_SKIP_OPTIMIZATION: 00704 extended_insert= opt_drop= opt_lock= quick= create_options= 00705 opt_disable_keys= lock_tables= opt_set_charset= 0; 00706 break; 00707 case (int) OPT_COMPACT: 00708 if (opt_compact) 00709 { 00710 opt_comments= opt_drop= opt_disable_keys= opt_lock= 0; 00711 opt_set_charset= 0; 00712 } 00713 case (int) OPT_TABLES: 00714 opt_databases=0; 00715 break; 00716 case (int) OPT_IGNORE_TABLE: 00717 { 00718 if (!strchr(argument, '.')) 00719 { 00720 fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n"); 00721 exit(1); 00722 } 00723 if (!hash_inited(&ignore_table)) 00724 init_table_rule_hash(&ignore_table); 00725 00726 if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0)))) 00727 exit(EX_EOM); 00728 break; 00729 } 00730 case (int) OPT_COMPATIBLE: 00731 { 00732 char buff[255]; 00733 char *end= compatible_mode_normal_str; 00734 int i; 00735 ulong mode; 00736 00737 opt_quoted= 1; 00738 opt_set_charset= 0; 00739 opt_compatible_mode_str= argument; 00740 opt_compatible_mode= find_set(&compatible_mode_typelib, 00741 argument, strlen(argument), 00742 &err_ptr, &err_len); 00743 if (err_len) 00744 { 00745 strmake(buff, err_ptr, min(sizeof(buff), err_len)); 00746 fprintf(stderr, "Invalid mode to --compatible: %s\n", buff); 00747 exit(1); 00748 } 00749 #if !defined(DBUG_OFF) 00750 { 00751 uint size_for_sql_mode= 0; 00752 const char **ptr; 00753 for (ptr= compatible_mode_names; *ptr; ptr++) 00754 size_for_sql_mode+= strlen(*ptr); 00755 size_for_sql_mode+= sizeof(compatible_mode_names)-1; 00756 DBUG_ASSERT(sizeof(compatible_mode_normal_str)>=size_for_sql_mode); 00757 } 00758 #endif 00759 mode= opt_compatible_mode; 00760 for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++) 00761 { 00762 if (mode & 1) 00763 { 00764 end= strmov(end, compatible_mode_names[i]); 00765 end= strmov(end, ","); 00766 } 00767 } 00768 if (end!=compatible_mode_normal_str) 00769 end[-1]= 0; 00770 /* 00771 Set charset to the default compiled value if it hasn't 00772 been reset yet by --default-character-set=xxx. 00773 */ 00774 if (default_charset == mysql_universal_client_charset) 00775 default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; 00776 break; 00777 } 00778 case (int) OPT_MYSQL_PROTOCOL: 00779 { 00780 if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0) 00781 { 00782 fprintf(stderr, "Unknown option to protocol: %s\n", argument); 00783 exit(1); 00784 } 00785 break; 00786 } 00787 } 00788 return 0; 00789 } 00790 00791 static int get_options(int *argc, char ***argv) 00792 { 00793 int ho_error; 00794 MYSQL_PARAMETERS *mysql_params= mysql_get_parameters(); 00795 00796 opt_max_allowed_packet= *mysql_params->p_max_allowed_packet; 00797 opt_net_buffer_length= *mysql_params->p_net_buffer_length; 00798 00799 md_result_file= stdout; 00800 load_defaults("my",load_default_groups,argc,argv); 00801 00802 if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) 00803 exit(ho_error); 00804 00805 *mysql_params->p_max_allowed_packet= opt_max_allowed_packet; 00806 *mysql_params->p_net_buffer_length= opt_net_buffer_length; 00807 00808 if (opt_delayed) 00809 opt_lock=0; /* Can't have lock with delayed */ 00810 if (!path && (enclosed || opt_enclosed || escaped || lines_terminated || 00811 fields_terminated)) 00812 { 00813 fprintf(stderr, 00814 "%s: You must use option --tab with --fields-...\n", my_progname); 00815 return(1); 00816 } 00817 00818 /* Ensure consistency of the set of binlog & locking options */ 00819 if (opt_delete_master_logs && !opt_master_data) 00820 opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL; 00821 if (opt_single_transaction && opt_lock_all_tables) 00822 { 00823 fprintf(stderr, "%s: You can't use --single-transaction and " 00824 "--lock-all-tables at the same time.\n", my_progname); 00825 return(1); 00826 } 00827 if (opt_master_data) 00828 opt_lock_all_tables= !opt_single_transaction; 00829 if (opt_single_transaction || opt_lock_all_tables) 00830 lock_tables= 0; 00831 if (enclosed && opt_enclosed) 00832 { 00833 fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname); 00834 return(1); 00835 } 00836 if ((opt_databases || opt_alldbs) && path) 00837 { 00838 fprintf(stderr, 00839 "%s: --databases or --all-databases can't be used with --tab.\n", 00840 my_progname); 00841 return(1); 00842 } 00843 if (strcmp(default_charset, charset_info->csname) && 00844 !(charset_info= get_charset_by_csname(default_charset, 00845 MY_CS_PRIMARY, MYF(MY_WME)))) 00846 exit(1); 00847 if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs)) 00848 { 00849 short_usage(); 00850 return 1; 00851 } 00852 if (tty_password) 00853 opt_password=get_tty_password(NullS); 00854 return(0); 00855 } /* get_options */ 00856 00857 00858 /* 00859 ** DB_error -- prints mysql error message and exits the program. 00860 */ 00861 static void DB_error(MYSQL *mysql, const char *when) 00862 { 00863 DBUG_ENTER("DB_error"); 00864 my_printf_error(0,"Got error: %d: %s %s", MYF(0), 00865 mysql_errno(mysql), mysql_error(mysql), when); 00866 safe_exit(EX_MYSQLERR); 00867 DBUG_VOID_RETURN; 00868 } /* DB_error */ 00869 00870 00871 /* 00872 Sends a query to server, optionally reads result, prints error message if 00873 some. 00874 00875 SYNOPSIS 00876 mysql_query_with_error_report() 00877 mysql_con connection to use 00878 res if non zero, result will be put there with 00879 mysql_store_result() 00880 query query to send to server 00881 00882 RETURN VALUES 00883 0 query sending and (if res!=0) result reading went ok 00884 1 error 00885 */ 00886 00887 static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res, 00888 const char *query) 00889 { 00890 if (mysql_query(mysql_con, query) || 00891 (res && !((*res)= mysql_store_result(mysql_con)))) 00892 { 00893 my_printf_error(0, "Couldn't execute '%s': %s (%d)", MYF(0), 00894 query, mysql_error(mysql_con), mysql_errno(mysql_con)); 00895 safe_exit(EX_MYSQLERR); 00896 return 1; 00897 } 00898 return 0; 00899 } 00900 00901 /* 00902 Open a new .sql file to dump the table or view into 00903 00904 SYNOPSIS 00905 open_sql_file_for_table 00906 name name of the table or view 00907 00908 RETURN VALUES 00909 0 Failed to open file 00910 > 0 Handle of the open file 00911 */ 00912 static FILE* open_sql_file_for_table(const char* table) 00913 { 00914 FILE* res; 00915 char filename[FN_REFLEN], tmp_path[FN_REFLEN]; 00916 convert_dirname(tmp_path,path,NullS); 00917 res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4), 00918 O_WRONLY, MYF(MY_WME)); 00919 return res; 00920 } 00921 00922 00923 static void safe_exit(int error) 00924 { 00925 if (!first_error) 00926 first_error= error; 00927 if (ignore_errors) 00928 return; 00929 if (mysql) 00930 mysql_close(mysql); 00931 exit(error); 00932 } 00933 /* safe_exit */ 00934 00935 00936 /* 00937 ** dbConnect -- connects to the host and selects DB. 00938 */ 00939 static int dbConnect(char *host, char *user,char *passwd) 00940 { 00941 char buff[20+FN_REFLEN]; 00942 DBUG_ENTER("dbConnect"); 00943 00944 verbose_msg("-- Connecting to %s...\n", host ? host : "localhost"); 00945 mysql_init(&mysql_connection); 00946 if (opt_compress) 00947 mysql_options(&mysql_connection,MYSQL_OPT_COMPRESS,NullS); 00948 #ifdef HAVE_OPENSSL 00949 if (opt_use_ssl) 00950 mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, 00951 opt_ssl_capath, opt_ssl_cipher); 00952 mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, 00953 (char*)&opt_ssl_verify_server_cert); 00954 #endif 00955 if (opt_protocol) 00956 mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); 00957 #ifdef HAVE_SMEM 00958 if (shared_memory_base_name) 00959 mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); 00960 #endif 00961 mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); 00962 if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd, 00963 NULL,opt_mysql_port,opt_mysql_unix_port, 00964 0))) 00965 { 00966 DB_error(&mysql_connection, "when trying to connect"); 00967 return 1; 00968 } 00969 /* 00970 Don't dump SET NAMES with a pre-4.1 server (bug#7997). 00971 */ 00972 if (mysql_get_server_version(&mysql_connection) < 40100) 00973 opt_set_charset= 0; 00974 /* 00975 As we're going to set SQL_MODE, it would be lost on reconnect, so we 00976 cannot reconnect. 00977 */ 00978 mysql->reconnect= 0; 00979 my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */", 00980 compatible_mode_normal_str); 00981 if (mysql_query_with_error_report(mysql, 0, buff)) 00982 { 00983 safe_exit(EX_MYSQLERR); 00984 return 1; 00985 } 00986 /* 00987 set time_zone to UTC to allow dumping date types between servers with 00988 different time zone settings 00989 */ 00990 if (opt_tz_utc) 00991 { 00992 my_snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */"); 00993 if (mysql_query_with_error_report(mysql, 0, buff)) 00994 { 00995 safe_exit(EX_MYSQLERR); 00996 return 1; 00997 } 00998 } 00999 return 0; 01000 } /* dbConnect */ 01001 01002 01003 /* 01004 ** dbDisconnect -- disconnects from the host. 01005 */ 01006 static void dbDisconnect(char *host) 01007 { 01008 verbose_msg("-- Disconnecting from %s...\n", host ? host : "localhost"); 01009 mysql_close(mysql); 01010 } /* dbDisconnect */ 01011 01012 01013 static void unescape(FILE *file,char *pos,uint length) 01014 { 01015 char *tmp; 01016 DBUG_ENTER("unescape"); 01017 if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME)))) 01018 { 01019 ignore_errors=0; /* Fatal error */ 01020 safe_exit(EX_MYSQLERR); /* Force exit */ 01021 } 01022 mysql_real_escape_string(&mysql_connection, tmp, pos, length); 01023 fputc('\'', file); 01024 fputs(tmp, file); 01025 fputc('\'', file); 01026 check_io(file); 01027 my_free(tmp, MYF(MY_WME)); 01028 DBUG_VOID_RETURN; 01029 } /* unescape */ 01030 01031 01032 static my_bool test_if_special_chars(const char *str) 01033 { 01034 #if MYSQL_VERSION_ID >= 32300 01035 for ( ; *str ; str++) 01036 if (!my_isvar(charset_info,*str) && *str != '$') 01037 return 1; 01038 #endif 01039 return 0; 01040 } /* test_if_special_chars */ 01041 01042 01043 01044 /* 01045 quote_name(name, buff, force) 01046 01047 Quotes char string, taking into account compatible mode 01048 01049 Args 01050 01051 name Unquoted string containing that which will be quoted 01052 buff The buffer that contains the quoted value, also returned 01053 force Flag to make it ignore 'test_if_special_chars' 01054 01055 Returns 01056 01057 buff quoted string 01058 01059 */ 01060 static char *quote_name(const char *name, char *buff, my_bool force) 01061 { 01062 char *to= buff; 01063 char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '\"' : '`'; 01064 01065 if (!force && !opt_quoted && !test_if_special_chars(name)) 01066 return (char*) name; 01067 *to++= qtype; 01068 while (*name) 01069 { 01070 if (*name == qtype) 01071 *to++= qtype; 01072 *to++= *name++; 01073 } 01074 to[0]= qtype; 01075 to[1]= 0; 01076 return buff; 01077 } /* quote_name */ 01078 01079 01080 /* 01081 Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>" 01082 01083 SYNOPSIS 01084 quote_for_like() 01085 name name of the table 01086 buff quoted name of the table 01087 01088 DESCRIPTION 01089 Quote \, _, ' and % characters 01090 01091 Note: Because MySQL uses the C escape syntax in strings 01092 (for example, '\n' to represent newline), you must double 01093 any '\' that you use in your LIKE strings. For example, to 01094 search for '\n', specify it as '\\n'. To search for '\', specify 01095 it as '\\\\' (the backslashes are stripped once by the parser 01096 and another time when the pattern match is done, leaving a 01097 single backslash to be matched). 01098 01099 Example: "t\1" => "t\\\\1" 01100 01101 */ 01102 static char *quote_for_like(const char *name, char *buff) 01103 { 01104 char *to= buff; 01105 *to++= '\''; 01106 while (*name) 01107 { 01108 if (*name == '\\') 01109 { 01110 *to++='\\'; 01111 *to++='\\'; 01112 *to++='\\'; 01113 } 01114 else if (*name == '\'' || *name == '_' || *name == '%') 01115 *to++= '\\'; 01116 *to++= *name++; 01117 } 01118 to[0]= '\''; 01119 to[1]= 0; 01120 return buff; 01121 } 01122 01123 01124 /* 01125 Quote and print a string. 01126 01127 SYNOPSIS 01128 print_quoted_xml() 01129 output - output file 01130 str - string to print 01131 len - its length 01132 01133 DESCRIPTION 01134 Quote '<' '>' '&' '\"' chars and print a string to the xml_file. 01135 */ 01136 01137 static void print_quoted_xml(FILE *xml_file, const char *str, ulong len) 01138 { 01139 const char *end; 01140 01141 for (end= str + len; str != end; str++) 01142 { 01143 switch (*str) { 01144 case '<': 01145 fputs("<", xml_file); 01146 break; 01147 case '>': 01148 fputs(">", xml_file); 01149 break; 01150 case '&': 01151 fputs("&", xml_file); 01152 break; 01153 case '\"': 01154 fputs(""", xml_file); 01155 break; 01156 default: 01157 fputc(*str, xml_file); 01158 break; 01159 } 01160 } 01161 check_io(xml_file); 01162 } 01163 01164 01165 /* 01166 Print xml tag with one attribute. 01167 01168 SYNOPSIS 01169 print_xml_tag1() 01170 xml_file - output file 01171 sbeg - line beginning 01172 stag_atr - tag and attribute 01173 sval - value of attribute 01174 send - line ending 01175 01176 DESCRIPTION 01177 Print tag with one attribute to the xml_file. Format is: 01178 sbeg<stag_atr="sval">send 01179 NOTE 01180 sval MUST be a NULL terminated string. 01181 sval string will be qouted before output. 01182 */ 01183 01184 static void print_xml_tag1(FILE * xml_file, const char* sbeg, 01185 const char* stag_atr, const char* sval, 01186 const char* send) 01187 { 01188 fputs(sbeg, xml_file); 01189 fputs("<", xml_file); 01190 fputs(stag_atr, xml_file); 01191 fputs("\"", xml_file); 01192 print_quoted_xml(xml_file, sval, strlen(sval)); 01193 fputs("\">", xml_file); 01194 fputs(send, xml_file); 01195 check_io(xml_file); 01196 } 01197 01198 01199 /* 01200 Print xml tag with for a field that is null 01201 01202 SYNOPSIS 01203 print_xml_null_tag() 01204 xml_file - output file 01205 sbeg - line beginning 01206 stag_atr - tag and attribute 01207 sval - value of attribute 01208 send - line ending 01209 01210 DESCRIPTION 01211 Print tag with one attribute to the xml_file. Format is: 01212 <stag_atr="sval" xsi:nil="true"/> 01213 NOTE 01214 sval MUST be a NULL terminated string. 01215 sval string will be qouted before output. 01216 */ 01217 01218 static void print_xml_null_tag(FILE * xml_file, const char* sbeg, 01219 const char* stag_atr, const char* sval, 01220 const char* send) 01221 { 01222 fputs(sbeg, xml_file); 01223 fputs("<", xml_file); 01224 fputs(stag_atr, xml_file); 01225 fputs("\"", xml_file); 01226 print_quoted_xml(xml_file, sval, strlen(sval)); 01227 fputs("\" xsi:nil=\"true\" />", xml_file); 01228 fputs(send, xml_file); 01229 check_io(xml_file); 01230 } 01231 01232 01233 /* 01234 Print xml tag with many attributes. 01235 01236 SYNOPSIS 01237 print_xml_row() 01238 xml_file - output file 01239 row_name - xml tag name 01240 tableRes - query result 01241 row - result row 01242 01243 DESCRIPTION 01244 Print tag with many attribute to the xml_file. Format is: 01245 \t\t<row_name Atr1="Val1" Atr2="Val2"... /> 01246 NOTE 01247 All atributes and values will be quoted before output. 01248 */ 01249 01250 static void print_xml_row(FILE *xml_file, const char *row_name, 01251 MYSQL_RES *tableRes, MYSQL_ROW *row) 01252 { 01253 uint i; 01254 MYSQL_FIELD *field; 01255 ulong *lengths= mysql_fetch_lengths(tableRes); 01256 01257 fprintf(xml_file, "\t\t<%s", row_name); 01258 check_io(xml_file); 01259 mysql_field_seek(tableRes, 0); 01260 for (i= 0; (field= mysql_fetch_field(tableRes)); i++) 01261 { 01262 if ((*row)[i]) 01263 { 01264 fputc(' ', xml_file); 01265 print_quoted_xml(xml_file, field->name, field->name_length); 01266 fputs("=\"", xml_file); 01267 print_quoted_xml(xml_file, (*row)[i], lengths[i]); 01268 fputc('"', xml_file); 01269 check_io(xml_file); 01270 } 01271 } 01272 fputs(" />\n", xml_file); 01273 check_io(xml_file); 01274 } 01275 01276 01277 /* 01278 create_delimiter 01279 Generate a new (null-terminated) string that does not exist in query 01280 and is therefore suitable for use as a query delimiter. Store this 01281 delimiter in delimiter_buff . 01282 01283 This is quite simple in that it doesn't even try to parse statements as an 01284 interpreter would. It merely returns a string that is not in the query, which 01285 is much more than adequate for constructing a delimiter. 01286 01287 RETURN 01288 ptr to the delimiter on Success 01289 NULL on Failure 01290 */ 01291 static char *create_delimiter(char *query, char *delimiter_buff, 01292 int delimiter_max_size) 01293 { 01294 int proposed_length; 01295 char *presence; 01296 01297 delimiter_buff[0]= ';'; /* start with one semicolon, and */ 01298 01299 for (proposed_length= 2; proposed_length < delimiter_max_size; 01300 delimiter_max_size++) { 01301 01302 delimiter_buff[proposed_length-1]= ';'; /* add semicolons, until */ 01303 delimiter_buff[proposed_length]= '\0'; 01304 01305 presence = strstr(query, delimiter_buff); 01306 if (presence == NULL) { /* the proposed delimiter is not in the query. */ 01307 return delimiter_buff; 01308 } 01309 01310 } 01311 return NULL; /* but if we run out of space, return nothing at all. */ 01312 } 01313 01314 01315 /* 01316 dump_events_for_db 01317 -- retrieves list of events for a given db, and prints out 01318 the CREATE EVENT statement into the output (the dump). 01319 01320 RETURN 01321 0 Success 01322 1 Error 01323 */ 01324 static uint dump_events_for_db(char *db) 01325 { 01326 char query_buff[QUERY_LENGTH]; 01327 char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3]; 01328 char *event_name; 01329 char delimiter[QUERY_LENGTH], *delimit_test; 01330 FILE *sql_file= md_result_file; 01331 MYSQL_RES *event_res, *event_list_res; 01332 MYSQL_ROW row, event_list_row; 01333 DBUG_ENTER("dump_events_for_db"); 01334 DBUG_PRINT("enter", ("db: '%s'", db)); 01335 01336 mysql_real_escape_string(mysql, db_name_buff, db, strlen(db)); 01337 01338 /* nice comments */ 01339 if (opt_comments) 01340 fprintf(sql_file, "\n--\n-- Dumping events for database '%s'\n--\n", db); 01341 01342 /* 01343 not using "mysql_query_with_error_report" because we may have not 01344 enough privileges to lock mysql.events. 01345 */ 01346 if (lock_tables) 01347 mysql_query(mysql, "LOCK TABLES mysql.event READ"); 01348 01349 if (mysql_query_with_error_report(mysql, &event_list_res, "show events")) 01350 { 01351 safe_exit(EX_MYSQLERR); 01352 DBUG_RETURN(0); 01353 } 01354 01355 strcpy(delimiter, ";"); 01356 if (mysql_num_rows(event_list_res) > 0) 01357 { 01358 while ((event_list_row= mysql_fetch_row(event_list_res)) != NULL) 01359 { 01360 event_name= quote_name(event_list_row[1], name_buff, 0); 01361 DBUG_PRINT("info", ("retrieving CREATE EVENT for %s", name_buff)); 01362 my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE EVENT %s", 01363 event_name); 01364 01365 if (mysql_query_with_error_report(mysql, &event_res, query_buff)) 01366 DBUG_RETURN(1); 01367 01368 while ((row= mysql_fetch_row(event_res)) != NULL) 01369 { 01370 /* 01371 if the user has EXECUTE privilege he can see event names, but not the 01372 event body! 01373 */ 01374 if (strlen(row[2]) != 0) 01375 { 01376 if (opt_drop) 01377 fprintf(sql_file, "/*!50106 DROP EVENT IF EXISTS %s */%s\n", 01378 event_name, delimiter); 01379 01380 delimit_test= create_delimiter(row[2], delimiter, sizeof(delimiter)); 01381 if (delimit_test == NULL) { 01382 fprintf(stderr, "%s: Warning: Can't dump event '%s'\n", 01383 event_name, my_progname); 01384 DBUG_RETURN(1); 01385 } 01386 01387 fprintf(sql_file, "DELIMITER %s\n", delimiter); 01388 fprintf(sql_file, "/*!50106 %s */ %s\n", row[2], delimiter); 01389 } 01390 } /* end of event printing */ 01391 } /* end of list of events */ 01392 fprintf(sql_file, "DELIMITER ;\n"); 01393 mysql_free_result(event_res); 01394 } 01395 mysql_free_result(event_list_res); 01396 01397 if (lock_tables) 01398 VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); 01399 DBUG_RETURN(0); 01400 } 01401 01402 01403 /* 01404 dump_routines_for_db 01405 -- retrieves list of routines for a given db, and prints out 01406 the CREATE PROCEDURE definition into the output (the dump). 01407 01408 This function has logic to print the appropriate syntax depending on whether 01409 this is a procedure or functions 01410 01411 RETURN 01412 0 Success 01413 1 Error 01414 */ 01415 01416 static uint dump_routines_for_db(char *db) 01417 { 01418 char query_buff[QUERY_LENGTH]; 01419 const char *routine_type[]= {"FUNCTION", "PROCEDURE"}; 01420 char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3]; 01421 char *routine_name; 01422 int i; 01423 FILE *sql_file= md_result_file; 01424 MYSQL_RES *routine_res, *routine_list_res; 01425 MYSQL_ROW row, routine_list_row; 01426 DBUG_ENTER("dump_routines_for_db"); 01427 DBUG_PRINT("enter", ("db: '%s'", db)); 01428 01429 mysql_real_escape_string(mysql, db_name_buff, db, strlen(db)); 01430 01431 /* nice comments */ 01432 if (opt_comments) 01433 fprintf(sql_file, "\n--\n-- Dumping routines for database '%s'\n--\n", db); 01434 01435 /* 01436 not using "mysql_query_with_error_report" because we may have not 01437 enough privileges to lock mysql.proc. 01438 */ 01439 if (lock_tables) 01440 mysql_query(mysql, "LOCK TABLES mysql.proc READ"); 01441 01442 fprintf(sql_file, "DELIMITER ;;\n"); 01443 01444 /* 0, retrieve and dump functions, 1, procedures */ 01445 for (i= 0; i <= 1; i++) 01446 { 01447 my_snprintf(query_buff, sizeof(query_buff), 01448 "SHOW %s STATUS WHERE Db = '%s'", 01449 routine_type[i], db_name_buff); 01450 01451 if (mysql_query_with_error_report(mysql, &routine_list_res, query_buff)) 01452 DBUG_RETURN(1); 01453 01454 if (mysql_num_rows(routine_list_res)) 01455 { 01456 01457 while ((routine_list_row= mysql_fetch_row(routine_list_res))) 01458 { 01459 routine_name= quote_name(routine_list_row[1], name_buff, 0); 01460 DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i], 01461 name_buff)); 01462 my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s", 01463 routine_type[i], routine_name); 01464 01465 if (mysql_query_with_error_report(mysql, &routine_res, query_buff)) 01466 DBUG_RETURN(1); 01467 01468 while ((row= mysql_fetch_row(routine_res))) 01469 { 01470 /* 01471 if the user has EXECUTE privilege he see routine names, but NOT the 01472 routine body of other routines that are not the creator of! 01473 */ 01474 DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d", 01475 routine_name, row[2], strlen(row[2]))); 01476 if (strlen(row[2])) 01477 { 01478 char *query_str= NULL; 01479 char *definer_begin; 01480 01481 if (opt_drop) 01482 fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n", 01483 routine_type[i], routine_name); 01484 01485 /* 01486 Cover DEFINER-clause in version-specific comments. 01487 01488 TODO: this is definitely a BAD IDEA to parse SHOW CREATE output. 01489 We should user INFORMATION_SCHEMA instead. The only problem is 01490 that now INFORMATION_SCHEMA does not provide information about 01491 routine parameters. 01492 */ 01493 01494 definer_begin= strstr(row[2], " DEFINER"); 01495 01496 if (definer_begin) 01497 { 01498 char *definer_end= strstr(definer_begin, " PROCEDURE"); 01499 01500 if (!definer_end) 01501 definer_end= strstr(definer_begin, " FUNCTION"); 01502 01503 if (definer_end) 01504 { 01505 char *query_str_tail; 01506 01507 /* 01508 Allocate memory for new query string: original string 01509 from SHOW statement and version-specific comments. 01510 */ 01511 query_str= alloc_query_str(strlen(row[2]) + 23); 01512 01513 query_str_tail= strnmov(query_str, row[2], 01514 definer_begin - row[2]); 01515 query_str_tail= strmov(query_str_tail, "*/ /*!50020"); 01516 query_str_tail= strnmov(query_str_tail, definer_begin, 01517 definer_end - definer_begin); 01518 query_str_tail= strxmov(query_str_tail, "*/ /*!50003", 01519 definer_end, NullS); 01520 } 01521 } 01522 01523 /* 01524 we need to change sql_mode only for the CREATE 01525 PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name 01526 */; 01527 fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n", 01528 row[1] /* sql_mode */); 01529 fprintf(sql_file, "/*!50003 %s */;;\n", 01530 (query_str != NULL ? query_str : row[2])); 01531 fprintf(sql_file, 01532 "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/" 01533 ";;\n"); 01534 01535 my_free(query_str, MYF(MY_ALLOW_ZERO_PTR)); 01536 } 01537 } /* end of routine printing */ 01538 } /* end of list of routines */ 01539 mysql_free_result(routine_res); 01540 } 01541 mysql_free_result(routine_list_res); 01542 } /* end of for i (0 .. 1) */ 01543 /* set the delimiter back to ';' */ 01544 fprintf(sql_file, "DELIMITER ;\n"); 01545 01546 if (lock_tables) 01547 VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); 01548 DBUG_RETURN(0); 01549 } 01550 01551 /* 01552 get_table_structure -- retrievs database structure, prints out corresponding 01553 CREATE statement and fills out insert_pat if the table is the type we will 01554 be dumping. 01555 01556 ARGS 01557 table - table name 01558 db - db name 01559 table_type - table type, e.g. "MyISAM" or "InnoDB", but also "VIEW" 01560 ignore_flag - what we must particularly ignore - see IGNORE_ defines above 01561 01562 RETURN 01563 number of fields in table, 0 if error 01564 */ 01565 01566 static uint get_table_structure(char *table, char *db, char *table_type, 01567 char *ignore_flag) 01568 { 01569 my_bool init=0, delayed, write_data, complete_insert; 01570 my_ulonglong num_fields; 01571 char *result_table, *opt_quoted_table; 01572 const char *insert_option; 01573 char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3]; 01574 char table_buff2[NAME_LEN*2+3], query_buff[QUERY_LENGTH]; 01575 FILE *sql_file = md_result_file; 01576 int len; 01577 MYSQL_RES *result; 01578 MYSQL_ROW row; 01579 01580 DBUG_ENTER("get_table_structure"); 01581 DBUG_PRINT("enter", ("db: %s table: %s", db, table)); 01582 01583 *ignore_flag= check_if_ignore_table(table, table_type); 01584 01585 delayed= opt_delayed; 01586 if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED)) 01587 { 01588 delayed= 0; 01589 verbose_msg("-- Warning: Unable to use delayed inserts for table '%s' " 01590 "because it's of type %s\n", table, table_type); 01591 } 01592 01593 complete_insert= 0; 01594 if ((write_data= !(*ignore_flag & IGNORE_DATA))) 01595 { 01596 complete_insert= opt_complete_insert; 01597 if (!insert_pat_inited) 01598 insert_pat_inited= init_dynamic_string(&insert_pat, "", 1024, 1024); 01599 else 01600 dynstr_set(&insert_pat, ""); 01601 } 01602 01603 insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " : 01604 delayed ? " DELAYED " : opt_ignore ? " IGNORE " : ""); 01605 01606 verbose_msg("-- Retrieving table structure for table %s...\n", table); 01607 01608 len= my_snprintf(query_buff, sizeof(query_buff), 01609 "SET OPTION SQL_QUOTE_SHOW_CREATE=%d", 01610 (opt_quoted || opt_keywords)); 01611 if (!create_options) 01612 strmov(query_buff+len, 01613 "/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */"); 01614 01615 result_table= quote_name(table, table_buff, 1); 01616 opt_quoted_table= quote_name(table, table_buff2, 0); 01617 01618 if (opt_order_by_primary) 01619 order_by = primary_key_fields(result_table); 01620 01621 if (!opt_xml && !mysql_query_with_error_report(mysql, 0, query_buff)) 01622 { 01623 /* using SHOW CREATE statement */ 01624 if (!opt_no_create_info) 01625 { 01626 /* Make an sql-file, if path was given iow. option -T was given */ 01627 char buff[20+FN_REFLEN]; 01628 MYSQL_FIELD *field; 01629 01630 my_snprintf(buff, sizeof(buff), "show create table %s", result_table); 01631 if (mysql_query_with_error_report(mysql, 0, buff)) 01632 { 01633 safe_exit(EX_MYSQLERR); 01634 DBUG_RETURN(0); 01635 } 01636 01637 if (path) 01638 { 01639 if (!(sql_file= open_sql_file_for_table(table))) 01640 { 01641 safe_exit(EX_MYSQLERR); 01642 DBUG_RETURN(0); 01643 } 01644 write_header(sql_file, db); 01645 } 01646 if (!opt_xml && opt_comments) 01647 { 01648 if (strcmp (table_type, "VIEW") == 0) /* view */ 01649 fprintf(sql_file, "\n--\n-- Temporary table structure for view %s\n--\n\n", 01650 result_table); 01651 else 01652 fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", 01653 result_table); 01654 check_io(sql_file); 01655 } 01656 if (opt_drop) 01657 { 01658 /* 01659 Even if the "table" is a view, we do a DROP TABLE here. The 01660 view-specific code below fills in the DROP VIEW. 01661 */ 01662 fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", 01663 opt_quoted_table); 01664 check_io(sql_file); 01665 } 01666 01667 result= mysql_store_result(mysql); 01668 field= mysql_fetch_field_direct(result, 0); 01669 if (strcmp(field->name, "View") == 0) 01670 { 01671 char *scv_buff = NULL; 01672 01673 verbose_msg("-- It's a view, create dummy table for view\n"); 01674 01675 /* save "show create" statement for later */ 01676 if ((row= mysql_fetch_row(result)) && (scv_buff=row[1])) 01677 scv_buff= my_strdup(scv_buff, MYF(0)); 01678 01679 mysql_free_result(result); 01680 01681 /* 01682 Create a table with the same name as the view and with columns of 01683 the same name in order to satisfy views that depend on this view. 01684 The table will be removed when the actual view is created. 01685 01686 The properties of each column, aside from the data type, are not 01687 preserved in this temporary table, because they are not necessary. 01688 01689 This will not be necessary once we can determine dependencies 01690 between views and can simply dump them in the appropriate order. 01691 */ 01692 my_snprintf(query_buff, sizeof(query_buff), 01693 "SHOW FIELDS FROM %s", result_table); 01694 if (mysql_query_with_error_report(mysql, 0, query_buff)) 01695 { 01696 /* 01697 View references invalid or privileged table/col/fun (err 1356), 01698 so we cannot create a stand-in table. Be defensive and dump 01699 a comment with the view's 'show create' statement. (Bug #17371) 01700 */ 01701 01702 if (mysql_errno(mysql) == ER_VIEW_INVALID) 01703 fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : ""); 01704 01705 my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); 01706 01707 safe_exit(EX_MYSQLERR); 01708 DBUG_RETURN(0); 01709 } 01710 else 01711 my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); 01712 01713 if ((result= mysql_store_result(mysql))) 01714 { 01715 if (mysql_num_rows(result)) 01716 { 01717 if (opt_drop) 01718 { 01719 /* 01720 We have already dropped any table of the same name 01721 above, so here we just drop the view. 01722 */ 01723 01724 fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n", 01725 opt_quoted_table); 01726 check_io(sql_file); 01727 } 01728 01729 fprintf(sql_file, "/*!50001 CREATE TABLE %s (\n", result_table); 01730 /* 01731 Get first row, following loop will prepend comma - keeps 01732 from having to know if the row being printed is last to 01733 determine if there should be a _trailing_ comma. 01734 */ 01735 row= mysql_fetch_row(result); 01736 01737 fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0), 01738 row[1]); 01739 01740 while((row= mysql_fetch_row(result))) 01741 { 01742 /* col name, col type */ 01743 fprintf(sql_file, ",\n %s %s", 01744 quote_name(row[0], name_buff, 0), row[1]); 01745 } 01746 fprintf(sql_file, "\n) */;\n"); 01747 check_io(sql_file); 01748 } 01749 } 01750 mysql_free_result(result); 01751 01752 if (path) 01753 my_fclose(sql_file, MYF(MY_WME)); 01754 01755 seen_views= 1; 01756 DBUG_RETURN(0); 01757 } 01758 01759 row= mysql_fetch_row(result); 01760 fprintf(sql_file, "%s;\n", row[1]); 01761 check_io(sql_file); 01762 mysql_free_result(result); 01763 } 01764 my_snprintf(query_buff, sizeof(query_buff), "show fields from %s", 01765 result_table); 01766 if (mysql_query_with_error_report(mysql, &result, query_buff)) 01767 { 01768 if (path) 01769 my_fclose(sql_file, MYF(MY_WME)); 01770 safe_exit(EX_MYSQLERR); 01771 DBUG_RETURN(0); 01772 } 01773 01774 /* 01775 If write_data is true, then we build up insert statements for 01776 the table's data. Note: in subsequent lines of code, this test 01777 will have to be performed each time we are appending to 01778 insert_pat. 01779 */ 01780 if (write_data) 01781 { 01782 if (opt_replace_into) 01783 dynstr_append_mem(&insert_pat, "REPLACE ", 8); 01784 else 01785 dynstr_append_mem(&insert_pat, "INSERT ", 7); 01786 dynstr_append(&insert_pat, insert_option); 01787 dynstr_append_mem(&insert_pat, "INTO ", 5); 01788 dynstr_append(&insert_pat, opt_quoted_table); 01789 if (complete_insert) 01790 { 01791 dynstr_append_mem(&insert_pat, " (", 2); 01792 } 01793 else 01794 { 01795 dynstr_append_mem(&insert_pat, " VALUES ", 8); 01796 if (!extended_insert) 01797 dynstr_append_mem(&insert_pat, "(", 1); 01798 } 01799 } 01800 01801 while ((row= mysql_fetch_row(result))) 01802 { 01803 if (complete_insert) 01804 { 01805 if (init) 01806 { 01807 dynstr_append_mem(&insert_pat, ", ", 2); 01808 } 01809 init=1; 01810 dynstr_append(&insert_pat, 01811 quote_name(row[SHOW_FIELDNAME], name_buff, 0)); 01812 } 01813 } 01814 num_fields= mysql_num_rows(result); 01815 mysql_free_result(result); 01816 } 01817 else 01818 { 01819 verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n", 01820 my_progname, mysql_error(mysql)); 01821 01822 my_snprintf(query_buff, sizeof(query_buff), "show fields from %s", 01823 result_table); 01824 if (mysql_query_with_error_report(mysql, &result, query_buff)) 01825 { 01826 safe_exit(EX_MYSQLERR); 01827 DBUG_RETURN(0); 01828 } 01829 01830 /* Make an sql-file, if path was given iow. option -T was given */ 01831 if (!opt_no_create_info) 01832 { 01833 if (path) 01834 { 01835 if (!(sql_file= open_sql_file_for_table(table))) 01836 { 01837 safe_exit(EX_MYSQLERR); 01838 DBUG_RETURN(0); 01839 } 01840 write_header(sql_file, db); 01841 } 01842 if (!opt_xml && opt_comments) 01843 fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", 01844 result_table); 01845 if (opt_drop) 01846 fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table); 01847 if (!opt_xml) 01848 fprintf(sql_file, "CREATE TABLE %s (\n", result_table); 01849 else 01850 print_xml_tag1(sql_file, "\t", "table_structure name=", table, "\n"); 01851 check_io(sql_file); 01852 } 01853 01854 if (write_data) 01855 { 01856 if (opt_replace_into) 01857 dynstr_append_mem(&insert_pat, "REPLACE ", 8); 01858 else 01859 dynstr_append_mem(&insert_pat, "INSERT ", 7); 01860 dynstr_append(&insert_pat, insert_option); 01861 dynstr_append_mem(&insert_pat, "INTO ", 5); 01862 dynstr_append(&insert_pat, result_table); 01863 if (opt_complete_insert) 01864 dynstr_append_mem(&insert_pat, " (", 2); 01865 else 01866 { 01867 dynstr_append_mem(&insert_pat, " VALUES ", 8); 01868 if (!extended_insert) 01869 dynstr_append_mem(&insert_pat, "(", 1); 01870 } 01871 } 01872 01873 while ((row= mysql_fetch_row(result))) 01874 { 01875 ulong *lengths= mysql_fetch_lengths(result); 01876 if (init) 01877 { 01878 if (!opt_xml && !opt_no_create_info) 01879 { 01880 fputs(",\n",sql_file); 01881 check_io(sql_file); 01882 } 01883 if (complete_insert) 01884 dynstr_append_mem(&insert_pat, ", ", 2); 01885 } 01886 init=1; 01887 if (opt_complete_insert) 01888 dynstr_append(&insert_pat, 01889 quote_name(row[SHOW_FIELDNAME], name_buff, 0)); 01890 if (!opt_no_create_info) 01891 { 01892 if (opt_xml) 01893 { 01894 print_xml_row(sql_file, "field", result, &row); 01895 continue; 01896 } 01897 01898 if (opt_keywords) 01899 fprintf(sql_file, " %s.%s %s", result_table, 01900 quote_name(row[SHOW_FIELDNAME],name_buff, 0), 01901 row[SHOW_TYPE]); 01902 else 01903 fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME], 01904 name_buff, 0), 01905 row[SHOW_TYPE]); 01906 if (row[SHOW_DEFAULT]) 01907 { 01908 fputs(" DEFAULT ", sql_file); 01909 unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]); 01910 } 01911 if (!row[SHOW_NULL][0]) 01912 fputs(" NOT NULL", sql_file); 01913 if (row[SHOW_EXTRA][0]) 01914 fprintf(sql_file, " %s",row[SHOW_EXTRA]); 01915 check_io(sql_file); 01916 } 01917 } 01918 num_fields= mysql_num_rows(result); 01919 mysql_free_result(result); 01920 if (!opt_no_create_info) 01921 { 01922 /* Make an sql-file, if path was given iow. option -T was given */ 01923 char buff[20+FN_REFLEN]; 01924 uint keynr,primary_key; 01925 my_snprintf(buff, sizeof(buff), "show keys from %s", result_table); 01926 if (mysql_query_with_error_report(mysql, &result, buff)) 01927 { 01928 if (mysql_errno(mysql) == ER_WRONG_OBJECT) 01929 { 01930 /* it is VIEW */ 01931 fputs("\t\t<options Comment=\"view\" />\n", sql_file); 01932 goto continue_xml; 01933 } 01934 fprintf(stderr, "%s: Can't get keys for table %s (%s)\n", 01935 my_progname, result_table, mysql_error(mysql)); 01936 if (path) 01937 my_fclose(sql_file, MYF(MY_WME)); 01938 safe_exit(EX_MYSQLERR); 01939 DBUG_RETURN(0); 01940 } 01941 01942 /* Find first which key is primary key */ 01943 keynr=0; 01944 primary_key=INT_MAX; 01945 while ((row= mysql_fetch_row(result))) 01946 { 01947 if (atoi(row[3]) == 1) 01948 { 01949 keynr++; 01950 #ifdef FORCE_PRIMARY_KEY 01951 if (atoi(row[1]) == 0 && primary_key == INT_MAX) 01952 primary_key=keynr; 01953 #endif 01954 if (!strcmp(row[2],"PRIMARY")) 01955 { 01956 primary_key=keynr; 01957 break; 01958 } 01959 } 01960 } 01961 mysql_data_seek(result,0); 01962 keynr=0; 01963 while ((row= mysql_fetch_row(result))) 01964 { 01965 if (opt_xml) 01966 { 01967 print_xml_row(sql_file, "key", result, &row); 01968 continue; 01969 } 01970 01971 if (atoi(row[3]) == 1) 01972 { 01973 if (keynr++) 01974 putc(')', sql_file); 01975 if (atoi(row[1])) /* Test if duplicate key */ 01976 /* Duplicate allowed */ 01977 fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0)); 01978 else if (keynr == primary_key) 01979 fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */ 01980 else 01981 fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff, 01982 0)); 01983 } 01984 else 01985 putc(',', sql_file); 01986 fputs(quote_name(row[4], name_buff, 0), sql_file); 01987 if (row[7]) 01988 fprintf(sql_file, " (%s)",row[7]); /* Sub key */ 01989 check_io(sql_file); 01990 } 01991 if (!opt_xml) 01992 { 01993 if (keynr) 01994 putc(')', sql_file); 01995 fputs("\n)",sql_file); 01996 check_io(sql_file); 01997 } 01998 01999 /* Get MySQL specific create options */ 02000 if (create_options) 02001 { 02002 char show_name_buff[NAME_LEN*2+2+24]; 02003 02004 /* Check memory for quote_for_like() */ 02005 my_snprintf(buff, sizeof(buff), "show table status like %s", 02006 quote_for_like(table, show_name_buff)); 02007 02008 if (mysql_query_with_error_report(mysql, &result, buff)) 02009 { 02010 if (mysql_errno(mysql) != ER_PARSE_ERROR) 02011 { /* If old MySQL version */ 02012 verbose_msg("-- Warning: Couldn't get status information for " \ 02013 "table %s (%s)\n", result_table,mysql_error(mysql)); 02014 } 02015 } 02016 else if (!(row= mysql_fetch_row(result))) 02017 { 02018 fprintf(stderr, 02019 "Error: Couldn't read status information for table %s (%s)\n", 02020 result_table,mysql_error(mysql)); 02021 } 02022 else 02023 { 02024 if (opt_xml) 02025 print_xml_row(sql_file, "options", result, &row); 02026 else 02027 { 02028 fputs("/*!",sql_file); 02029 print_value(sql_file,result,row,"engine=","Engine",0); 02030 print_value(sql_file,result,row,"","Create_options",0); 02031 print_value(sql_file,result,row,"comment=","Comment",1); 02032 fputs(" */",sql_file); 02033 check_io(sql_file); 02034 } 02035 } 02036 mysql_free_result(result); /* Is always safe to free */ 02037 } 02038 continue_xml: 02039 if (!opt_xml) 02040 fputs(";\n", sql_file); 02041 else 02042 fputs("\t</table_structure>\n", sql_file); 02043 check_io(sql_file); 02044 } 02045 } 02046 if (opt_complete_insert) 02047 { 02048 dynstr_append_mem(&insert_pat, ") VALUES ", 9); 02049 if (!extended_insert) 02050 dynstr_append_mem(&insert_pat, "(", 1); 02051 } 02052 if (sql_file != md_result_file) 02053 { 02054 fputs("\n", sql_file); 02055 write_footer(sql_file); 02056 my_fclose(sql_file, MYF(MY_WME)); 02057 } 02058 DBUG_RETURN(num_fields); 02059 } /* get_table_structure */ 02060 02061 02062 /* 02063 02064 dump_triggers_for_table 02065 02066 Dumps the triggers given a table/db name. This should be called after 02067 the tables have been dumped in case a trigger depends on the existence 02068 of a table 02069 02070 */ 02071 02072 static void dump_triggers_for_table (char *table, char *db) 02073 { 02074 char *result_table; 02075 char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3]; 02076 char query_buff[QUERY_LENGTH]; 02077 uint old_opt_compatible_mode=opt_compatible_mode; 02078 FILE *sql_file = md_result_file; 02079 MYSQL_RES *result; 02080 MYSQL_ROW row; 02081 02082 DBUG_ENTER("dump_triggers_for_table"); 02083 DBUG_PRINT("enter", ("db: %s, table: %s", db, table)); 02084 02085 /* Do not use ANSI_QUOTES on triggers in dump */ 02086 opt_compatible_mode&= ~MASK_ANSI_QUOTES; 02087 result_table= quote_name(table, table_buff, 1); 02088 02089 my_snprintf(query_buff, sizeof(query_buff), 02090 "SHOW TRIGGERS LIKE %s", 02091 quote_for_like(table, name_buff)); 02092 02093 if (mysql_query_with_error_report(mysql, &result, query_buff)) 02094 { 02095 if (path) 02096 my_fclose(sql_file, MYF(MY_WME)); 02097 safe_exit(EX_MYSQLERR); 02098 DBUG_VOID_RETURN; 02099 } 02100 if (mysql_num_rows(result)) 02101 fprintf(sql_file, "\n/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n\ 02102 DELIMITER ;;\n"); 02103 while ((row= mysql_fetch_row(result))) 02104 { 02105 fprintf(sql_file, 02106 "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n" 02107 "/*!50003 CREATE */ ", 02108 row[6] /* sql_mode */); 02109 02110 if (mysql_num_fields(result) > 7) 02111 { 02112 /* 02113 mysqldump can be run against the server, that does not support definer 02114 in triggers (there is no DEFINER column in SHOW TRIGGERS output). So, 02115 we should check if we have this column before accessing it. 02116 */ 02117 02118 uint user_name_len; 02119 char user_name_str[USERNAME_LENGTH + 1]; 02120 char quoted_user_name_str[USERNAME_LENGTH * 2 + 3]; 02121 uint host_name_len; 02122 char host_name_str[HOSTNAME_LENGTH + 1]; 02123 char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3]; 02124 02125 parse_user(row[7], strlen(row[7]), user_name_str, &user_name_len, 02126 host_name_str, &host_name_len); 02127 02128 fprintf(sql_file, 02129 "/*!50017 DEFINER=%s@%s */ ", 02130 quote_name(user_name_str, quoted_user_name_str, FALSE), 02131 quote_name(host_name_str, quoted_host_name_str, FALSE)); 02132 } 02133 02134 fprintf(sql_file, 02135 "/*!50003 TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n\n", 02136 quote_name(row[0], name_buff, 0), /* Trigger */ 02137 row[4], /* Timing */ 02138 row[1], /* Event */ 02139 result_table, 02140 (strchr(" \t\n\r", *(row[3]))) ? "" : " ", 02141 row[3] /* Statement */); 02142 } 02143 if (mysql_num_rows(result)) 02144 fprintf(sql_file, 02145 "DELIMITER ;\n" 02146 "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n"); 02147 mysql_free_result(result); 02148 /* 02149 make sure to set back opt_compatible mode to 02150 original value 02151 */ 02152 opt_compatible_mode=old_opt_compatible_mode; 02153 DBUG_VOID_RETURN; 02154 } 02155 02156 static char *add_load_option(char *ptr,const char *object, 02157 const char *statement) 02158 { 02159 if (object) 02160 { 02161 /* Don't escape hex constants */ 02162 if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X')) 02163 ptr= strxmov(ptr," ",statement," ",object,NullS); 02164 else 02165 { 02166 /* char constant; escape */ 02167 ptr= strxmov(ptr," ",statement," '",NullS); 02168 ptr= field_escape(ptr,object,(uint) strlen(object)); 02169 *ptr++= '\''; 02170 } 02171 } 02172 return ptr; 02173 } /* add_load_option */ 02174 02175 02176 /* 02177 Allow the user to specify field terminator strings like: 02178 "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline) 02179 This is done by doubling ' and add a end -\ if needed to avoid 02180 syntax errors from the SQL parser. 02181 */ 02182 02183 static char *field_escape(char *to,const char *from,uint length) 02184 { 02185 const char *end; 02186 uint end_backslashes=0; 02187 02188 for (end= from+length; from != end; from++) 02189 { 02190 *to++= *from; 02191 if (*from == '\\') 02192 end_backslashes^=1; /* find odd number of backslashes */ 02193 else 02194 { 02195 if (*from == '\'' && !end_backslashes) 02196 *to++= *from; /* We want a duplicate of "'" for MySQL */ 02197 end_backslashes=0; 02198 } 02199 } 02200 /* Add missing backslashes if user has specified odd number of backs.*/ 02201 if (end_backslashes) 02202 *to++= '\\'; 02203 return to; 02204 } /* field_escape */ 02205 02206 02207 static char *alloc_query_str(ulong size) 02208 { 02209 char *query; 02210 02211 if (!(query= (char*) my_malloc(size, MYF(MY_WME)))) 02212 { 02213 ignore_errors= 0; /* Fatal error */ 02214 safe_exit(EX_MYSQLERR); /* Force exit */ 02215 } 02216 return query; 02217 } 02218 02219 02220 /* 02221 02222 SYNOPSIS 02223 dump_table() 02224 02225 dump_table saves database contents as a series of INSERT statements. 02226 02227 ARGS 02228 table - table name 02229 db - db name 02230 02231 RETURNS 02232 void 02233 */ 02234 02235 static void dump_table(char *table, char *db) 02236 { 02237 char ignore_flag; 02238 char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3]; 02239 char table_type[NAME_LEN]; 02240 char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table; 02241 char *query= query_buf; 02242 int error= 0; 02243 ulong rownr, row_break, total_length, init_length; 02244 uint num_fields; 02245 MYSQL_RES *res; 02246 MYSQL_FIELD *field; 02247 MYSQL_ROW row; 02248 DBUG_ENTER("dump_table"); 02249 02250 /* 02251 Make sure you get the create table info before the following check for 02252 --no-data flag below. Otherwise, the create table info won't be printed. 02253 */ 02254 num_fields= get_table_structure(table, db, table_type, &ignore_flag); 02255 02256 /* 02257 The "table" could be a view. If so, we don't do anything here. 02258 */ 02259 if (strcmp (table_type, "VIEW") == 0) 02260 return; 02261 02262 /* Check --no-data flag */ 02263 if (opt_no_data) 02264 { 02265 verbose_msg("-- Skipping dump data for table '%s', --no-data was used\n", 02266 table); 02267 DBUG_VOID_RETURN; 02268 } 02269 02270 DBUG_PRINT("info", 02271 ("ignore_flag: %x num_fields: %d", (int) ignore_flag, 02272 num_fields)); 02273 /* 02274 If the table type is a merge table or any type that has to be 02275 _completely_ ignored and no data dumped 02276 */ 02277 if (ignore_flag & IGNORE_DATA) 02278 { 02279 verbose_msg("-- Warning: Skipping data for table '%s' because " \ 02280 "it's of type %s\n", table, table_type); 02281 DBUG_VOID_RETURN; 02282 } 02283 /* Check that there are any fields in the table */ 02284 if (num_fields == 0) 02285 { 02286 verbose_msg("-- Skipping dump data for table '%s', it has no fields\n", 02287 table); 02288 DBUG_VOID_RETURN; 02289 } 02290 02291 result_table= quote_name(table,table_buff, 1); 02292 opt_quoted_table= quote_name(table, table_buff2, 0); 02293 02294 verbose_msg("-- Sending SELECT query...\n"); 02295 if (path) 02296 { 02297 char filename[FN_REFLEN], tmp_path[FN_REFLEN]; 02298 convert_dirname(tmp_path,path,NullS); 02299 my_load_path(tmp_path, tmp_path, NULL); 02300 fn_format(filename, table, tmp_path, ".txt", 4); 02301 my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if 02302 filename wasn't deleted */ 02303 to_unix_path(filename); 02304 my_snprintf(query, QUERY_LENGTH, 02305 "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'", 02306 filename); 02307 end= strend(query); 02308 02309 if (fields_terminated || enclosed || opt_enclosed || escaped) 02310 end= strmov(end, " FIELDS"); 02311 end= add_load_option(end, fields_terminated, " TERMINATED BY"); 02312 end= add_load_option(end, enclosed, " ENCLOSED BY"); 02313 end= add_load_option(end, opt_enclosed, " OPTIONALLY ENCLOSED BY"); 02314 end= add_load_option(end, escaped, " ESCAPED BY"); 02315 end= add_load_option(end, lines_terminated, " LINES TERMINATED BY"); 02316 *end= '\0'; 02317 02318 my_snprintf(buff, sizeof(buff), " FROM %s", result_table); 02319 end= strmov(end,buff); 02320 if (where || order_by) 02321 { 02322 query = alloc_query_str((ulong) ((end - query) + 1 + 02323 (where ? strlen(where) + 7 : 0) + 02324 (order_by ? strlen(order_by) + 10 : 0))); 02325 end = strmov(query, query_buf); 02326 02327 if (where) 02328 end = strxmov(end, " WHERE ", where, NullS); 02329 if (order_by) 02330 end = strxmov(end, " ORDER BY ", order_by, NullS); 02331 } 02332 if (mysql_real_query(mysql, query, (uint) (end - query))) 02333 { 02334 DB_error(mysql, "when executing 'SELECT INTO OUTFILE'"); 02335 DBUG_VOID_RETURN; 02336 } 02337 } 02338 else 02339 { 02340 if (!opt_xml && opt_comments) 02341 { 02342 fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n", 02343 result_table); 02344 check_io(md_result_file); 02345 } 02346 my_snprintf(query, QUERY_LENGTH, 02347 "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s", 02348 result_table); 02349 if (where || order_by) 02350 { 02351 query = alloc_query_str((ulong) (strlen(query) + 1 + 02352 (where ? strlen(where) + 7 : 0) + 02353 (order_by ? strlen(order_by) + 10 : 0))); 02354 end = strmov(query, query_buf); 02355 02356 if (where) 02357 { 02358 if (!opt_xml && opt_comments) 02359 { 02360 fprintf(md_result_file, "-- WHERE: %s\n", where); 02361 check_io(md_result_file); 02362 } 02363 end = strxmov(end, " WHERE ", where, NullS); 02364 } 02365 if (order_by) 02366 { 02367 if (!opt_xml && opt_comments) 02368 { 02369 fprintf(md_result_file, "-- ORDER BY: %s\n", order_by); 02370 check_io(md_result_file); 02371 } 02372 end = strxmov(end, " ORDER BY ", order_by, NullS); 02373 } 02374 } 02375 if (!opt_xml && !opt_compact) 02376 { 02377 fputs("\n", md_result_file); 02378 check_io(md_result_file); 02379 } 02380 if (mysql_query_with_error_report(mysql, 0, query)) 02381 DB_error(mysql, "when retrieving data from server"); 02382 if (quick) 02383 res=mysql_use_result(mysql); 02384 else 02385 res=mysql_store_result(mysql); 02386 if (!res) 02387 { 02388 DB_error(mysql, "when retrieving data from server"); 02389 goto err; 02390 } 02391 02392 verbose_msg("-- Retrieving rows...\n"); 02393 if (mysql_num_fields(res) != num_fields) 02394 { 02395 fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n", 02396 my_progname, result_table); 02397 error= EX_CONSCHECK; 02398 goto err; 02399 } 02400 02401 if (opt_lock) 02402 { 02403 fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table); 02404 check_io(md_result_file); 02405 } 02406 /* Moved disable keys to after lock per bug 15977 */ 02407 if (opt_disable_keys) 02408 { 02409 fprintf(md_result_file, "/*!40000 ALTER TABLE %s DISABLE KEYS */;\n", 02410 opt_quoted_table); 02411 check_io(md_result_file); 02412 } 02413 02414 total_length= opt_net_buffer_length; /* Force row break */ 02415 row_break=0; 02416 rownr=0; 02417 init_length=(uint) insert_pat.length+4; 02418 if (opt_xml) 02419 print_xml_tag1(md_result_file, "\t", "table_data name=", table, "\n"); 02420 02421 if (opt_autocommit) 02422 { 02423 fprintf(md_result_file, "set autocommit=0;\n"); 02424 check_io(md_result_file); 02425 } 02426 02427 while ((row= mysql_fetch_row(res))) 02428 { 02429 uint i; 02430 ulong *lengths= mysql_fetch_lengths(res); 02431 rownr++; 02432 if (!extended_insert && !opt_xml) 02433 { 02434 fputs(insert_pat.str,md_result_file); 02435 check_io(md_result_file); 02436 } 02437 mysql_field_seek(res,0); 02438 02439 if (opt_xml) 02440 { 02441 fputs("\t<row>\n", md_result_file); 02442 check_io(md_result_file); 02443 } 02444 02445 for (i = 0; i < mysql_num_fields(res); i++) 02446 { 02447 int is_blob; 02448 ulong length= lengths[i]; 02449 02450 if (!(field = mysql_fetch_field(res))) 02451 { 02452 my_snprintf(query, QUERY_LENGTH, 02453 "%s: Not enough fields from table %s! Aborting.\n", 02454 my_progname, result_table); 02455 fputs(query,stderr); 02456 error= EX_CONSCHECK; 02457 goto err; 02458 } 02459 02460 /* 02461 63 is my_charset_bin. If charsetnr is not 63, 02462 we have not a BLOB but a TEXT column. 02463 we'll dump in hex only BLOB columns. 02464 */ 02465 is_blob= (opt_hex_blob && field->charsetnr == 63 && 02466 (field->type == MYSQL_TYPE_BIT || 02467 field->type == MYSQL_TYPE_STRING || 02468 field->type == MYSQL_TYPE_VAR_STRING || 02469 field->type == MYSQL_TYPE_VARCHAR || 02470 field->type == MYSQL_TYPE_BLOB || 02471 field->type == MYSQL_TYPE_LONG_BLOB || 02472 field->type == MYSQL_TYPE_MEDIUM_BLOB || 02473 field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0; 02474 if (extended_insert) 02475 { 02476 if (i == 0) 02477 dynstr_set(&extended_row,"("); 02478 else 02479 dynstr_append(&extended_row,","); 02480 02481 if (row[i]) 02482 { 02483 if (length) 02484 { 02485 if (!IS_NUM_FIELD(field)) 02486 { 02487 /* 02488 "length * 2 + 2" is OK for both HEX and non-HEX modes: 02489 - In HEX mode we need exactly 2 bytes per character 02490 plus 2 bytes for '0x' prefix. 02491 - In non-HEX mode we need up to 2 bytes per character, 02492 plus 2 bytes for leading and trailing '\'' characters. 02493 */ 02494 if (dynstr_realloc(&extended_row,length * 2+2)) 02495 { 02496 fputs("Aborting dump (out of memory)",stderr); 02497 error= EX_EOM; 02498 goto err; 02499 } 02500 if (opt_hex_blob && is_blob) 02501 { 02502 dynstr_append(&extended_row, "0x"); 02503 extended_row.length+= mysql_hex_string(extended_row.str + 02504 extended_row.length, 02505 row[i], length); 02506 extended_row.str[extended_row.length]= '\0'; 02507 } 02508 else 02509 { 02510 dynstr_append(&extended_row,"'"); 02511 extended_row.length += 02512 mysql_real_escape_string(&mysql_connection, 02513 &extended_row.str[extended_row.length], 02514 row[i],length); 02515 extended_row.str[extended_row.length]='\0'; 02516 dynstr_append(&extended_row,"'"); 02517 } 02518 } 02519 else 02520 { 02521 /* change any strings ("inf", "-inf", "nan") into NULL */ 02522 char *ptr = row[i]; 02523 if (my_isalpha(charset_info, *ptr) || (*ptr == '-' && 02524 my_isalpha(charset_info, ptr[1]))) 02525 dynstr_append(&extended_row, "NULL"); 02526 else 02527 { 02528 if (field->type == FIELD_TYPE_DECIMAL) 02529 { 02530 /* add " signs around */ 02531 dynstr_append(&extended_row, "'"); 02532 dynstr_append(&extended_row, ptr); 02533 dynstr_append(&extended_row, "'"); 02534 } 02535 else 02536 dynstr_append(&extended_row, ptr); 02537 } 02538 } 02539 } 02540 else 02541 dynstr_append(&extended_row,"''"); 02542 } 02543 else if (dynstr_append(&extended_row,"NULL")) 02544 { 02545 fputs("Aborting dump (out of memory)",stderr); 02546 error= EX_EOM; 02547 goto err; 02548 } 02549 } 02550 else 02551 { 02552 if (i && !opt_xml) 02553 { 02554 fputc(',', md_result_file); 02555 check_io(md_result_file); 02556 } 02557 if (row[i]) 02558 { 02559 if (!IS_NUM_FIELD(field)) 02560 { 02561 if (opt_xml) 02562 { 02563 print_xml_tag1(md_result_file, "\t\t", "field name=", 02564 field->name, ""); 02565 print_quoted_xml(md_result_file, row[i], length); 02566 fputs("</field>\n", md_result_file); 02567 } 02568 else if (opt_hex_blob && is_blob && length) 02569 { 02570 /* sakaik got the idea to to provide blob's in hex notation. */ 02571 char *ptr= row[i], *end= ptr + length; 02572 fputs("0x", md_result_file); 02573 for (; ptr < end ; ptr++) 02574 fprintf(md_result_file, "%02X", *((uchar *)ptr)); 02575 } 02576 else 02577 unescape(md_result_file, row[i], length); 02578 } 02579 else 02580 { 02581 /* change any strings ("inf", "-inf", "nan") into NULL */ 02582 char *ptr = row[i]; 02583 if (opt_xml) 02584 { 02585 print_xml_tag1(md_result_file, "\t\t", "field name=", 02586 field->name, ""); 02587 fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL", 02588 md_result_file); 02589 fputs("</field>\n", md_result_file); 02590 } 02591 else if (my_isalpha(charset_info, *ptr) || 02592 (*ptr == '-' && my_isalpha(charset_info, ptr[1]))) 02593 fputs("NULL", md_result_file); 02594 else if (field->type == FIELD_TYPE_DECIMAL) 02595 { 02596 /* add " signs around */ 02597 fputc('\'', md_result_file); 02598 fputs(ptr, md_result_file); 02599 fputc('\'', md_result_file); 02600 } 02601 else 02602 fputs(ptr, md_result_file); 02603 } 02604 } 02605 else 02606 { 02607 /* The field value is NULL */ 02608 if (!opt_xml) 02609 fputs("NULL", md_result_file); 02610 else 02611 print_xml_null_tag(md_result_file, "\t\t", "field name=", 02612 field->name, "\n"); 02613 } 02614 check_io(md_result_file); 02615 } 02616 } 02617 02618 if (opt_xml) 02619 { 02620 fputs("\t</row>\n", md_result_file); 02621 check_io(md_result_file); 02622 } 02623 02624 if (extended_insert) 02625 { 02626 ulong row_length; 02627 dynstr_append(&extended_row,")"); 02628 row_length = 2 + extended_row.length; 02629 if (total_length + row_length < opt_net_buffer_length) 02630 { 02631 total_length += row_length; 02632 fputc(',',md_result_file); /* Always row break */ 02633 fputs(extended_row.str,md_result_file); 02634 } 02635 else 02636 { 02637 if (row_break) 02638 fputs(";\n", md_result_file); 02639 row_break=1; /* This is first row */ 02640 02641 fputs(insert_pat.str,md_result_file); 02642 fputs(extended_row.str,md_result_file); 02643 total_length = row_length+init_length; 02644 } 02645 check_io(md_result_file); 02646 } 02647 else if (!opt_xml) 02648 { 02649 fputs(");\n", md_result_file); 02650 check_io(md_result_file); 02651 } 02652 } 02653 02654 /* XML - close table tag and supress regular output */ 02655 if (opt_xml) 02656 fputs("\t</table_data>\n", md_result_file); 02657 else if (extended_insert && row_break) 02658 fputs(";\n", md_result_file); /* If not empty table */ 02659 fflush(md_result_file); 02660 check_io(md_result_file); 02661 if (mysql_errno(mysql)) 02662 { 02663 my_snprintf(query, QUERY_LENGTH, 02664 "%s: Error %d: %s when dumping table %s at row: %ld\n", 02665 my_progname, 02666 mysql_errno(mysql), 02667 mysql_error(mysql), 02668 result_table, 02669 rownr); 02670 fputs(query,stderr); 02671 error= EX_CONSCHECK; 02672 goto err; 02673 } 02674 02675 /* Moved enable keys to before unlock per bug 15977 */ 02676 if (opt_disable_keys) 02677 { 02678 fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n", 02679 opt_quoted_table); 02680 check_io(md_result_file); 02681 } 02682 if (opt_lock) 02683 { 02684 fputs("UNLOCK TABLES;\n", md_result_file); 02685 check_io(md_result_file); 02686 } 02687 if (opt_autocommit) 02688 { 02689 fprintf(md_result_file, "commit;\n"); 02690 check_io(md_result_file); 02691 } 02692 mysql_free_result(res); 02693 if (query != query_buf) 02694 my_free(query, MYF(MY_ALLOW_ZERO_PTR)); 02695 } 02696 DBUG_VOID_RETURN; 02697 02698 err: 02699 if (query != query_buf) 02700 my_free(query, MYF(MY_ALLOW_ZERO_PTR)); 02701 safe_exit(error); 02702 DBUG_VOID_RETURN; 02703 } /* dump_table */ 02704 02705 02706 static char *getTableName(int reset) 02707 { 02708 static MYSQL_RES *res = NULL; 02709 MYSQL_ROW row; 02710 02711 if (!res) 02712 { 02713 if (!(res = mysql_list_tables(mysql,NullS))) 02714 return(NULL); 02715 } 02716 if ((row = mysql_fetch_row(res))) 02717 return((char*) row[0]); 02718 02719 if (reset) 02720 mysql_data_seek(res,0); /* We want to read again */ 02721 else 02722 { 02723 mysql_free_result(res); 02724 res = NULL; 02725 } 02726 return(NULL); 02727 } /* getTableName */ 02728 02729 02730 /* 02731 dump all logfile groups and tablespaces 02732 */ 02733 02734 static int dump_all_tablespaces() 02735 { 02736 MYSQL_ROW row; 02737 MYSQL_RES *tableres; 02738 char buf[FN_REFLEN]; 02739 int first; 02740 02741 if (mysql_query_with_error_report(mysql, &tableres, 02742 "SELECT DISTINCT" 02743 " LOGFILE_GROUP_NAME," 02744 " FILE_NAME," 02745 " TOTAL_EXTENTS," 02746 " INITIAL_SIZE," 02747 " ENGINE" 02748 " FROM INFORMATION_SCHEMA.FILES" 02749 " WHERE FILE_TYPE = \"UNDO LOG\"" 02750 " ORDER BY LOGFILE_GROUP_NAME")) 02751 return 1; 02752 02753 buf[0]= 0; 02754 while ((row= mysql_fetch_row(tableres))) 02755 { 02756 if (strcmp(buf, row[0]) != 0) 02757 first= 1; 02758 if (first) 02759 { 02760 if (!opt_xml && opt_comments) 02761 { 02762 fprintf(md_result_file,"\n--\n-- Logfile group: %s\n--\n", row[0]); 02763 check_io(md_result_file); 02764 } 02765 fprintf(md_result_file, "\nCREATE"); 02766 } 02767 else 02768 { 02769 fprintf(md_result_file, "\nALTER"); 02770 } 02771 fprintf(md_result_file, 02772 " LOGFILE GROUP %s\n" 02773 " ADD UNDOFILE '%s'\n", 02774 row[0], 02775 row[1]); 02776 if (first) 02777 { 02778 fprintf(md_result_file, 02779 " UNDO_BUFFER_SIZE %s\n", 02780 row[2]); 02781 } 02782 fprintf(md_result_file, 02783 " INITIAL_SIZE %s\n" 02784 " ENGINE=%s;\n", 02785 row[3], 02786 row[4]); 02787 check_io(md_result_file); 02788 if (first) 02789 { 02790 first= 0; 02791 strxmov(buf, row[0], NullS); 02792 } 02793 } 02794 02795 if (mysql_query_with_error_report(mysql, &tableres, 02796 "SELECT DISTINCT" 02797 " TABLESPACE_NAME," 02798 " FILE_NAME," 02799 " LOGFILE_GROUP_NAME," 02800 " EXTENT_SIZE," 02801 " INITIAL_SIZE," 02802 " ENGINE" 02803 " FROM INFORMATION_SCHEMA.FILES" 02804 " WHERE FILE_TYPE = \"DATAFILE\"" 02805 " ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME")) 02806 return 1; 02807 02808 buf[0]= 0; 02809 while ((row= mysql_fetch_row(tableres))) 02810 { 02811 if (strcmp(buf, row[0]) != 0) 02812 first= 1; 02813 if (first) 02814 { 02815 if (!opt_xml && opt_comments) 02816 { 02817 fprintf(md_result_file,"\n--\n-- Tablespace: %s\n--\n", row[0]); 02818 check_io(md_result_file); 02819 } 02820 fprintf(md_result_file, "\nCREATE"); 02821 } 02822 else 02823 { 02824 fprintf(md_result_file, "\nALTER"); 02825 } 02826 fprintf(md_result_file, 02827 " TABLESPACE %s\n" 02828 " ADD DATAFILE '%s'\n", 02829 row[0], 02830 row[1]); 02831 if (first) 02832 { 02833 fprintf(md_result_file, 02834 " USE LOGFILE GROUP %s\n" 02835 " EXTENT_SIZE %s\n", 02836 row[2], 02837 row[3]); 02838 } 02839 fprintf(md_result_file, 02840 " INITIAL_SIZE %s\n" 02841 " ENGINE=%s;\n", 02842 row[4], 02843 row[5]); 02844 check_io(md_result_file); 02845 if (first) 02846 { 02847 first= 0; 02848 strxmov(buf, row[0], NullS); 02849 } 02850 } 02851 return 0; 02852 } 02853 02854 static int dump_all_databases() 02855 { 02856 MYSQL_ROW row; 02857 MYSQL_RES *tableres; 02858 int result=0; 02859 02860 if (mysql_query_with_error_report(mysql, &tableres, "SHOW DATABASES")) 02861 return 1; 02862 while ((row = mysql_fetch_row(tableres))) 02863 { 02864 if (dump_all_tables_in_db(row[0])) 02865 result=1; 02866 } 02867 if (seen_views) 02868 { 02869 if (mysql_query(mysql, "SHOW DATABASES") || 02870 !(tableres = mysql_store_result(mysql))) 02871 { 02872 my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", 02873 MYF(0), mysql_error(mysql)); 02874 return 1; 02875 } 02876 while ((row = mysql_fetch_row(tableres))) 02877 { 02878 if (dump_all_views_in_db(row[0])) 02879 result=1; 02880 } 02881 } 02882 return result; 02883 } 02884 /* dump_all_databases */ 02885 02886 02887 static int dump_databases(char **db_names) 02888 { 02889 int result=0; 02890 char **db; 02891 for (db= db_names ; *db ; db++) 02892 { 02893 if (dump_all_tables_in_db(*db)) 02894 result=1; 02895 } 02896 if (!result && seen_views) 02897 { 02898 for (db= db_names ; *db ; db++) 02899 { 02900 if (dump_all_views_in_db(*db)) 02901 result=1; 02902 } 02903 } 02904 return result; 02905 } /* dump_databases */ 02906 02907 02908 static int init_dumping(char *database) 02909 { 02910 if (mysql_get_server_version(mysql) >= 50003 && 02911 !my_strcasecmp(&my_charset_latin1, database, "information_schema")) 02912 return 1; 02913 02914 if (mysql_select_db(mysql, database)) 02915 { 02916 DB_error(mysql, "when selecting the database"); 02917 return 1; /* If --force */ 02918 } 02919 if (!path && !opt_xml) 02920 { 02921 if (opt_databases || opt_alldbs) 02922 { 02923 /* 02924 length of table name * 2 (if name contains quotes), 2 quotes and 0 02925 */ 02926 char quoted_database_buf[NAME_LEN*2+3]; 02927 char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); 02928 if (opt_comments) 02929 { 02930 fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase); 02931 check_io(md_result_file); 02932 } 02933 if (!opt_create_db) 02934 { 02935 char qbuf[256]; 02936 MYSQL_ROW row; 02937 MYSQL_RES *dbinfo; 02938 02939 my_snprintf(qbuf, sizeof(qbuf), 02940 "SHOW CREATE DATABASE IF NOT EXISTS %s", 02941 qdatabase); 02942 02943 if (mysql_query(mysql, qbuf) || !(dbinfo = mysql_store_result(mysql))) 02944 { 02945 /* Old server version, dump generic CREATE DATABASE */ 02946 if (opt_drop_database) 02947 fprintf(md_result_file, 02948 "\n/*!40000 DROP DATABASE IF EXISTS %s;*/\n", 02949 qdatabase); 02950 fprintf(md_result_file, 02951 "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n", 02952 qdatabase); 02953 } 02954 else 02955 { 02956 if (opt_drop_database) 02957 fprintf(md_result_file, 02958 "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n", 02959 qdatabase); 02960 row = mysql_fetch_row(dbinfo); 02961 if (row[1]) 02962 { 02963 fprintf(md_result_file,"\n%s;\n",row[1]); 02964 } 02965 } 02966 } 02967 fprintf(md_result_file,"\nUSE %s;\n", qdatabase); 02968 check_io(md_result_file); 02969 } 02970 } 02971 if (extended_insert && init_dynamic_string(&extended_row, "", 1024, 1024)) 02972 exit(EX_EOM); 02973 return 0; 02974 } /* init_dumping */ 02975 02976 02977 my_bool include_table(byte* hash_key, uint len) 02978 { 02979 if (hash_search(&ignore_table, (byte*) hash_key, len)) 02980 return FALSE; 02981 02982 return TRUE; 02983 } 02984 02985 02986 static int dump_all_tables_in_db(char *database) 02987 { 02988 char *table; 02989 uint numrows; 02990 char table_buff[NAME_LEN*2+3]; 02991 02992 char hash_key[2*NAME_LEN+2]; /* "db.tablename" */ 02993 char *afterdot; 02994 02995 afterdot= strmov(hash_key, database); 02996 *afterdot++= '.'; 02997 02998 if (!strcmp(database, NDB_REP_DB)) /* Skip cluster internal database */ 02999 return 0; 03000 if (init_dumping(database)) 03001 return 1; 03002 if (opt_xml) 03003 print_xml_tag1(md_result_file, "", "database name=", database, "\n"); 03004 if (lock_tables) 03005 { 03006 DYNAMIC_STRING query; 03007 init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); 03008 for (numrows= 0 ; (table= getTableName(1)) ; numrows++) 03009 { 03010 dynstr_append(&query, quote_name(table, table_buff, 1)); 03011 dynstr_append(&query, " READ /*!32311 LOCAL */,"); 03012 } 03013 if (numrows && mysql_real_query(mysql, query.str, query.length-1)) 03014 DB_error(mysql, "when using LOCK TABLES"); 03015 /* We shall continue here, if --force was given */ 03016 dynstr_free(&query); 03017 } 03018 if (flush_logs) 03019 { 03020 if (mysql_refresh(mysql, REFRESH_LOG)) 03021 DB_error(mysql, "when doing refresh"); 03022 /* We shall continue here, if --force was given */ 03023 } 03024 while ((table= getTableName(0))) 03025 { 03026 char *end= strmov(afterdot, table); 03027 if (include_table(hash_key, end - hash_key)) 03028 { 03029 dump_table(table,database); 03030 my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); 03031 order_by= 0; 03032 if (opt_dump_triggers && ! opt_xml && 03033 mysql_get_server_version(mysql) >= 50009) 03034 dump_triggers_for_table(table, database); 03035 } 03036 } 03037 if (opt_events && !opt_xml && 03038 mysql_get_server_version(mysql) >= 50106) 03039 { 03040 DBUG_PRINT("info", ("Dumping events for database %s", database)); 03041 dump_events_for_db(database); 03042 } 03043 if (opt_routines && !opt_xml && 03044 mysql_get_server_version(mysql) >= 50009) 03045 { 03046 DBUG_PRINT("info", ("Dumping routines for database %s", database)); 03047 dump_routines_for_db(database); 03048 } 03049 if (opt_xml) 03050 { 03051 fputs("</database>\n", md_result_file); 03052 check_io(md_result_file); 03053 } 03054 if (lock_tables) 03055 VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); 03056 return 0; 03057 } /* dump_all_tables_in_db */ 03058 03059 03060 /* 03061 dump structure of views of database 03062 03063 SYNOPSIS 03064 dump_all_views_in_db() 03065 database database name 03066 03067 RETURN 03068 0 OK 03069 1 ERROR 03070 */ 03071 03072 static my_bool dump_all_views_in_db(char *database) 03073 { 03074 char *table; 03075 uint numrows; 03076 char table_buff[NAME_LEN*2+3]; 03077 03078 if (mysql_select_db(mysql, database)) 03079 { 03080 DB_error(mysql, "when selecting the database"); 03081 return 1; 03082 } 03083 if (opt_databases || opt_alldbs) 03084 { 03085 char quoted_database_buf[NAME_LEN*2+3]; 03086 char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); 03087 if (opt_comments) 03088 { 03089 fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase); 03090 check_io(md_result_file); 03091 } 03092 fprintf(md_result_file,"\nUSE %s;\n", qdatabase); 03093 check_io(md_result_file); 03094 } 03095 if (opt_xml) 03096 print_xml_tag1(md_result_file, "", "database name=", database, "\n"); 03097 if (lock_tables) 03098 { 03099 DYNAMIC_STRING query; 03100 init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); 03101 for (numrows= 0 ; (table= getTableName(1)); numrows++) 03102 { 03103 dynstr_append(&query, quote_name(table, table_buff, 1)); 03104 dynstr_append(&query, " READ /*!32311 LOCAL */,"); 03105 } 03106 if (numrows && mysql_real_query(mysql, query.str, query.length-1)) 03107 DB_error(mysql, "when using LOCK TABLES"); 03108 /* We shall continue here, if --force was given */ 03109 dynstr_free(&query); 03110 } 03111 if (flush_logs) 03112 { 03113 if (mysql_refresh(mysql, REFRESH_LOG)) 03114 DB_error(mysql, "when doing refresh"); 03115 /* We shall continue here, if --force was given */ 03116 } 03117 while ((table= getTableName(0))) 03118 get_view_structure(table, database); 03119 if (opt_xml) 03120 { 03121 fputs("</database>\n", md_result_file); 03122 check_io(md_result_file); 03123 } 03124 if (lock_tables) 03125 VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); 03126 return 0; 03127 } /* dump_all_tables_in_db */ 03128 03129 03130 /* 03131 get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual 03132 table name from the server for the table name given on the command line. 03133 we do this because the table name given on the command line may be a 03134 different case (e.g. T1 vs t1) 03135 03136 RETURN 03137 pointer to the table name 03138 0 if error 03139 */ 03140 03141 static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root) 03142 { 03143 char *name= 0; 03144 MYSQL_RES *table_res; 03145 MYSQL_ROW row; 03146 char query[50 + 2*NAME_LEN]; 03147 char show_name_buff[FN_REFLEN]; 03148 DBUG_ENTER("get_actual_table_name"); 03149 03150 /* Check memory for quote_for_like() */ 03151 DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff)); 03152 my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", 03153 quote_for_like(old_table_name, show_name_buff)); 03154 03155 if (mysql_query_with_error_report(mysql, 0, query)) 03156 { 03157 safe_exit(EX_MYSQLERR); 03158 } 03159 03160 if ((table_res= mysql_store_result(mysql))) 03161 { 03162 my_ulonglong num_rows= mysql_num_rows(table_res); 03163 if (num_rows > 0) 03164 { 03165 ulong *lengths; 03166 /* 03167 Return first row 03168 TODO: Return all matching rows 03169 */ 03170 row= mysql_fetch_row(table_res); 03171 lengths= mysql_fetch_lengths(table_res); 03172 name= strmake_root(root, row[0], lengths[0]); 03173 } 03174 mysql_free_result(table_res); 03175 } 03176 DBUG_PRINT("exit", ("new_table_name: %s", name)); 03177 DBUG_RETURN(name); 03178 } 03179 03180 03181 static int dump_selected_tables(char *db, char **table_names, int tables) 03182 { 03183 char table_buff[NAME_LEN*+3]; 03184 DYNAMIC_STRING lock_tables_query; 03185 MEM_ROOT root; 03186 char **dump_tables, **pos, **end; 03187 DBUG_ENTER("dump_selected_tables"); 03188 03189 if (init_dumping(db)) 03190 DBUG_RETURN(1); 03191 03192 init_alloc_root(&root, 8192, 0); 03193 if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *)))) 03194 exit(EX_EOM); 03195 03196 init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024); 03197 for (; tables > 0 ; tables-- , table_names++) 03198 { 03199 /* the table name passed on commandline may be wrong case */ 03200 if ((*pos= get_actual_table_name(*table_names, &root))) 03201 { 03202 /* Add found table name to lock_tables_query */ 03203 if (lock_tables) 03204 { 03205 dynstr_append(&lock_tables_query, quote_name(*pos, table_buff, 1)); 03206 dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,"); 03207 } 03208 pos++; 03209 } 03210 else 03211 { 03212 my_printf_error(0,"Couldn't find table: \"%s\"\n", MYF(0), 03213 *table_names); 03214 safe_exit(EX_ILLEGAL_TABLE); 03215 /* We shall countinue here, if --force was given */ 03216 } 03217 } 03218 end= pos; 03219 03220 if (lock_tables) 03221 { 03222 if (mysql_real_query(mysql, lock_tables_query.str, 03223 lock_tables_query.length-1)) 03224 DB_error(mysql, "when doing LOCK TABLES"); 03225 /* We shall countinue here, if --force was given */ 03226 } 03227 dynstr_free(&lock_tables_query); 03228 if (flush_logs) 03229 { 03230 if (mysql_refresh(mysql, REFRESH_LOG)) 03231 DB_error(mysql, "when doing refresh"); 03232 /* We shall countinue here, if --force was given */ 03233 } 03234 if (opt_xml) 03235 print_xml_tag1(md_result_file, "", "database name=", db, "\n"); 03236 03237 /* Dump each selected table */ 03238 for (pos= dump_tables; pos < end; pos++) 03239 { 03240 DBUG_PRINT("info",("Dumping table %s", *pos)); 03241 dump_table(*pos, db); 03242 if (opt_dump_triggers && 03243 mysql_get_server_version(mysql) >= 50009) 03244 dump_triggers_for_table(*pos, db); 03245 } 03246 03247 /* Dump each selected view */ 03248 if (seen_views) 03249 { 03250 for (pos= dump_tables; pos < end; pos++) 03251 get_view_structure(*pos, db); 03252 } 03253 if (opt_events && !opt_xml && 03254 mysql_get_server_version(mysql) >= 50106) 03255 { 03256 DBUG_PRINT("info", ("Dumping events for database %s", db)); 03257 dump_events_for_db(db); 03258 } 03259 /* obtain dump of routines (procs/functions) */ 03260 if (opt_routines && !opt_xml && 03261 mysql_get_server_version(mysql) >= 50009) 03262 { 03263 DBUG_PRINT("info", ("Dumping routines for database %s", db)); 03264 dump_routines_for_db(db); 03265 } 03266 free_root(&root, MYF(0)); 03267 my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); 03268 order_by= 0; 03269 if (opt_xml) 03270 { 03271 fputs("</database>\n", md_result_file); 03272 check_io(md_result_file); 03273 } 03274 if (lock_tables) 03275 VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); 03276 DBUG_RETURN(0); 03277 } /* dump_selected_tables */ 03278 03279 03280 static int do_show_master_status(MYSQL *mysql_con) 03281 { 03282 MYSQL_ROW row; 03283 MYSQL_RES *master; 03284 const char *comment_prefix= 03285 (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : ""; 03286 if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS")) 03287 { 03288 return 1; 03289 } 03290 else 03291 { 03292 row = mysql_fetch_row(master); 03293 if (row && row[0] && row[1]) 03294 { 03295 /* SHOW MASTER STATUS reports file and position */ 03296 if (opt_comments) 03297 fprintf(md_result_file, 03298 "\n--\n-- Position to start replication or point-in-time " 03299 "recovery from\n--\n\n"); 03300 fprintf(md_result_file, 03301 "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", 03302 comment_prefix, row[0], row[1]); 03303 check_io(md_result_file); 03304 } 03305 else if (!ignore_errors) 03306 { 03307 /* SHOW MASTER STATUS reports nothing and --force is not enabled */ 03308 my_printf_error(0, "Error: Binlogging on server not active", 03309 MYF(0)); 03310 mysql_free_result(master); 03311 return 1; 03312 } 03313 mysql_free_result(master); 03314 } 03315 return 0; 03316 } 03317 03318 03319 static int do_flush_tables_read_lock(MYSQL *mysql_con) 03320 { 03321 /* 03322 We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES 03323 will wait but will not stall the whole mysqld, and when the long update is 03324 done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So, 03325 FLUSH TABLES is to lower the probability of a stage where both mysqldump 03326 and most client connections are stalled. Of course, if a second long 03327 update starts between the two FLUSHes, we have that bad stall. 03328 */ 03329 return 03330 ( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") || 03331 mysql_query_with_error_report(mysql_con, 0, 03332 "FLUSH TABLES WITH READ LOCK") ); 03333 } 03334 03335 03336 static int do_unlock_tables(MYSQL *mysql_con) 03337 { 03338 return mysql_query_with_error_report(mysql_con, 0, "UNLOCK TABLES"); 03339 } 03340 03341 03342 static int do_reset_master(MYSQL *mysql_con) 03343 { 03344 return mysql_query_with_error_report(mysql_con, 0, "RESET MASTER"); 03345 } 03346 03347 03348 static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now) 03349 { 03350 /* 03351 We use BEGIN for old servers. --single-transaction --master-data will fail 03352 on old servers, but that's ok as it was already silently broken (it didn't 03353 do a consistent read, so better tell people frankly, with the error). 03354 03355 We want the first consistent read to be used for all tables to dump so we 03356 need the REPEATABLE READ level (not anything lower, for example READ 03357 COMMITTED would give one new consistent read per dumped table). 03358 */ 03359 return (mysql_query_with_error_report(mysql_con, 0, 03360 "SET SESSION TRANSACTION ISOLATION " 03361 "LEVEL REPEATABLE READ") || 03362 mysql_query_with_error_report(mysql_con, 0, 03363 consistent_read_now ? 03364 "START TRANSACTION " 03365 "WITH CONSISTENT SNAPSHOT" : 03366 "BEGIN")); 03367 } 03368 03369 03370 static ulong find_set(TYPELIB *lib, const char *x, uint length, 03371 char **err_pos, uint *err_len) 03372 { 03373 const char *end= x + length; 03374 ulong found= 0; 03375 uint find; 03376 char buff[255]; 03377 03378 *err_pos= 0; /* No error yet */ 03379 while (end > x && my_isspace(charset_info, end[-1])) 03380 end--; 03381 03382 *err_len= 0; 03383 if (x != end) 03384 { 03385 const char *start= x; 03386 for (;;) 03387 { 03388 const char *pos= start; 03389 uint var_len; 03390 03391 for (; pos != end && *pos != ','; pos++) ; 03392 var_len= (uint) (pos - start); 03393 strmake(buff, start, min(sizeof(buff), var_len)); 03394 find= find_type(buff, lib, var_len); 03395 if (!find) 03396 { 03397 *err_pos= (char*) start; 03398 *err_len= var_len; 03399 } 03400 else 03401 found|= ((longlong) 1 << (find - 1)); 03402 if (pos == end) 03403 break; 03404 start= pos + 1; 03405 } 03406 } 03407 return found; 03408 } 03409 03410 03411 /* Print a value with a prefix on file */ 03412 static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, 03413 const char *prefix, const char *name, 03414 int string_value) 03415 { 03416 MYSQL_FIELD *field; 03417 mysql_field_seek(result, 0); 03418 03419 for ( ; (field = mysql_fetch_field(result)) ; row++) 03420 { 03421 if (!strcmp(field->name,name)) 03422 { 03423 if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */ 03424 { 03425 fputc(' ',file); 03426 fputs(prefix, file); 03427 if (string_value) 03428 unescape(file,row[0],(uint) strlen(row[0])); 03429 else 03430 fputs(row[0], file); 03431 check_io(file); 03432 return; 03433 } 03434 } 03435 } 03436 return; /* This shouldn't happen */ 03437 } /* print_value */ 03438 03439 03440 /* 03441 03442 SYNOPSIS 03443 03444 Check if we the table is one of the table types that should be ignored: 03445 MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts. 03446 If the table should be altogether ignored, it returns a TRUE, FALSE if it 03447 should not be ignored. If the user has selected to use INSERT DELAYED, it 03448 sets the value of the bool pointer supports_delayed_inserts to 0 if not 03449 supported, 1 if it is supported. 03450 03451 ARGS 03452 03453 check_if_ignore_table() 03454 table_name Table name to check 03455 table_type Type of table 03456 03457 GLOBAL VARIABLES 03458 mysql MySQL connection 03459 verbose Write warning messages 03460 03461 RETURN 03462 char (bit value) See IGNORE_ values at top 03463 */ 03464 03465 char check_if_ignore_table(const char *table_name, char *table_type) 03466 { 03467 char result= IGNORE_NONE; 03468 char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN]; 03469 MYSQL_RES *res; 03470 MYSQL_ROW row; 03471 DBUG_ENTER("check_if_ignore_table"); 03472 03473 /* Check memory for quote_for_like() */ 03474 DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff)); 03475 my_snprintf(buff, sizeof(buff), "show table status like %s", 03476 quote_for_like(table_name, show_name_buff)); 03477 if (mysql_query_with_error_report(mysql, &res, buff)) 03478 { 03479 if (mysql_errno(mysql) != ER_PARSE_ERROR) 03480 { /* If old MySQL version */ 03481 verbose_msg("-- Warning: Couldn't get status information for " \ 03482 "table %s (%s)\n", table_name,mysql_error(mysql)); 03483 DBUG_RETURN(result); /* assume table is ok */ 03484 } 03485 } 03486 if (!(row= mysql_fetch_row(res))) 03487 { 03488 fprintf(stderr, 03489 "Error: Couldn't read status information for table %s (%s)\n", 03490 table_name, mysql_error(mysql)); 03491 mysql_free_result(res); 03492 DBUG_RETURN(result); /* assume table is ok */ 03493 } 03494 if (!(row[1])) 03495 strmake(table_type, "VIEW", NAME_LEN-1); 03496 else 03497 { 03498 /* 03499 If the table type matches any of these, we do support delayed inserts. 03500 Note: we do not want to skip dumping this table if if is not one of 03501 these types, but we do want to use delayed inserts in the dump if 03502 the table type is _NOT_ one of these types 03503 */ 03504 strmake(table_type, row[1], NAME_LEN-1); 03505 if (opt_delayed) 03506 { 03507 if (strcmp(table_type,"MyISAM") && 03508 strcmp(table_type,"ISAM") && 03509 strcmp(table_type,"ARCHIVE") && 03510 strcmp(table_type,"HEAP") && 03511 strcmp(table_type,"MEMORY")) 03512 result= IGNORE_INSERT_DELAYED; 03513 } 03514 03515 /* 03516 If these two types, we do want to skip dumping the table 03517 */ 03518 if (!opt_no_data && 03519 (!strcmp(table_type,"MRG_MyISAM") || !strcmp(table_type,"MRG_ISAM"))) 03520 result= IGNORE_DATA; 03521 } 03522 mysql_free_result(res); 03523 DBUG_RETURN(result); 03524 } 03525 03526 03527 /* 03528 Get string of comma-separated primary key field names 03529 03530 SYNOPSIS 03531 char *primary_key_fields(const char *table_name) 03532 RETURNS pointer to allocated buffer (must be freed by caller) 03533 table_name quoted table name 03534 03535 DESCRIPTION 03536 Use SHOW KEYS FROM table_name, allocate a buffer to hold the 03537 field names, and then build that string and return the pointer 03538 to that buffer. 03539 03540 Returns NULL if there is no PRIMARY or UNIQUE key on the table, 03541 or if there is some failure. It is better to continue to dump 03542 the table unsorted, rather than exit without dumping the data. 03543 */ 03544 03545 static char *primary_key_fields(const char *table_name) 03546 { 03547 MYSQL_RES *res = NULL; 03548 MYSQL_ROW row; 03549 /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */ 03550 char show_keys_buff[15 + NAME_LEN * 2 + 3]; 03551 uint result_length = 0; 03552 char *result = 0; 03553 03554 my_snprintf(show_keys_buff, sizeof(show_keys_buff), 03555 "SHOW KEYS FROM %s", table_name); 03556 if (mysql_query(mysql, show_keys_buff) || 03557 !(res = mysql_store_result(mysql))) 03558 { 03559 fprintf(stderr, "Warning: Couldn't read keys from table %s;" 03560 " records are NOT sorted (%s)\n", 03561 table_name, mysql_error(mysql)); 03562 /* Don't exit, because it's better to print out unsorted records */ 03563 goto cleanup; 03564 } 03565 03566 /* 03567 * Figure out the length of the ORDER BY clause result. 03568 * Note that SHOW KEYS is ordered: a PRIMARY key is always the first 03569 * row, and UNIQUE keys come before others. So we only need to check 03570 * the first key, not all keys. 03571 */ 03572 if ((row = mysql_fetch_row(res)) && atoi(row[1]) == 0) 03573 { 03574 /* Key is unique */ 03575 do 03576 result_length += strlen(row[4]) + 1; /* + 1 for ',' or \0 */ 03577 while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1); 03578 } 03579 03580 /* Build the ORDER BY clause result */ 03581 if (result_length) 03582 { 03583 char *end; 03584 /* result (terminating \0 is already in result_length) */ 03585 result = my_malloc(result_length + 10, MYF(MY_WME)); 03586 if (!result) 03587 { 03588 fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n"); 03589 goto cleanup; 03590 } 03591 mysql_data_seek(res, 0); 03592 row = mysql_fetch_row(res); 03593 end = strmov(result, row[4]); 03594 while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1) 03595 end = strxmov(end, ",", row[4], NullS); 03596 } 03597 03598 cleanup: 03599 if (res) 03600 mysql_free_result(res); 03601 03602 return result; 03603 } 03604 03605 03606 /* 03607 Replace a substring 03608 03609 SYNOPSIS 03610 replace 03611 ds_str The string to search and perform the replace in 03612 search_str The string to search for 03613 search_len Length of the string to search for 03614 replace_str The string to replace with 03615 replace_len Length of the string to replace with 03616 03617 RETURN 03618 0 String replaced 03619 1 Could not find search_str in str 03620 */ 03621 03622 static int replace(DYNAMIC_STRING *ds_str, 03623 const char *search_str, ulong search_len, 03624 const char *replace_str, ulong replace_len) 03625 { 03626 DYNAMIC_STRING ds_tmp; 03627 const char *start= strstr(ds_str->str, search_str); 03628 if (!start) 03629 return 1; 03630 init_dynamic_string(&ds_tmp, "", 03631 ds_str->length + replace_len, 256); 03632 dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str); 03633 dynstr_append_mem(&ds_tmp, replace_str, replace_len); 03634 dynstr_append(&ds_tmp, start + search_len); 03635 dynstr_set(ds_str, ds_tmp.str); 03636 dynstr_free(&ds_tmp); 03637 return 0; 03638 } 03639 03640 03641 /* 03642 Getting VIEW structure 03643 03644 SYNOPSIS 03645 get_view_structure() 03646 table view name 03647 db db name 03648 03649 RETURN 03650 0 OK 03651 1 ERROR 03652 */ 03653 03654 static my_bool get_view_structure(char *table, char* db) 03655 { 03656 MYSQL_RES *table_res; 03657 MYSQL_ROW row; 03658 MYSQL_FIELD *field; 03659 char *result_table, *opt_quoted_table; 03660 char table_buff[NAME_LEN*2+3]; 03661 char table_buff2[NAME_LEN*2+3]; 03662 char query[QUERY_LENGTH]; 03663 FILE *sql_file = md_result_file; 03664 DBUG_ENTER("get_view_structure"); 03665 03666 if (opt_no_create_info) /* Don't write table creation info */ 03667 DBUG_RETURN(0); 03668 03669 verbose_msg("-- Retrieving view structure for table %s...\n", table); 03670 03671 #ifdef NOT_REALLY_USED_YET 03672 sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", 03673 (opt_quoted || opt_keywords)); 03674 #endif 03675 03676 result_table= quote_name(table, table_buff, 1); 03677 opt_quoted_table= quote_name(table, table_buff2, 0); 03678 03679 my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %s", result_table); 03680 if (mysql_query_with_error_report(mysql, &table_res, query)) 03681 { 03682 safe_exit(EX_MYSQLERR); 03683 DBUG_RETURN(0); 03684 } 03685 03686 /* Check if this is a view */ 03687 field= mysql_fetch_field_direct(table_res, 0); 03688 if (strcmp(field->name, "View") != 0) 03689 { 03690 verbose_msg("-- It's base table, skipped\n"); 03691 DBUG_RETURN(0); 03692 } 03693 03694 /* If requested, open separate .sql file for this view */ 03695 if (path) 03696 { 03697 if (!(sql_file= open_sql_file_for_table(table))) 03698 { 03699 safe_exit(EX_MYSQLERR); 03700 DBUG_RETURN(1); 03701 } 03702 write_header(sql_file, db); 03703 } 03704 03705 if (!opt_xml && opt_comments) 03706 { 03707 fprintf(sql_file, "\n--\n-- Final view structure for view %s\n--\n\n", 03708 result_table); 03709 check_io(sql_file); 03710 } 03711 if (opt_drop) 03712 { 03713 fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n", 03714 opt_quoted_table); 03715 fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n", 03716 opt_quoted_table); 03717 check_io(sql_file); 03718 } 03719 03720 03721 my_snprintf(query, sizeof(query), 03722 "SELECT CHECK_OPTION, DEFINER, SECURITY_TYPE " \ 03723 "FROM information_schema.views " \ 03724 "WHERE table_name=\"%s\" AND table_schema=\"%s\"", table, db); 03725 if (mysql_query(mysql, query)) 03726 { 03727 /* 03728 Use the raw output from SHOW CREATE TABLE if 03729 information_schema query fails. 03730 */ 03731 row= mysql_fetch_row(table_res); 03732 fprintf(sql_file, "/*!50001 %s */;\n", row[1]); 03733 check_io(sql_file); 03734 mysql_free_result(table_res); 03735 } 03736 else 03737 { 03738 char *ptr; 03739 ulong *lengths; 03740 char search_buf[256], replace_buf[256]; 03741 ulong search_len, replace_len; 03742 DYNAMIC_STRING ds_view; 03743 03744 /* Save the result of SHOW CREATE TABLE in ds_view */ 03745 row= mysql_fetch_row(table_res); 03746 lengths= mysql_fetch_lengths(table_res); 03747 init_dynamic_string(&ds_view, row[1], lengths[1] + 1, 1024); 03748 mysql_free_result(table_res); 03749 03750 /* Get the result from "select ... information_schema" */ 03751 if (!(table_res= mysql_store_result(mysql)) || 03752 !(row= mysql_fetch_row(table_res))) 03753 { 03754 safe_exit(EX_MYSQLERR); 03755 DBUG_RETURN(1); 03756 } 03757 03758 lengths= mysql_fetch_lengths(table_res); 03759 03760 /* 03761 "WITH %s CHECK OPTION" is available from 5.0.2 03762 Surround it with !50002 comments 03763 */ 03764 if (strcmp(row[0], "NONE")) 03765 { 03766 03767 ptr= search_buf; 03768 search_len= (ulong)(strxmov(ptr, "WITH ", row[0], 03769 " CHECK OPTION", NullS) - ptr); 03770 ptr= replace_buf; 03771 replace_len=(ulong)(strxmov(ptr, "*/\n/*!50002 WITH ", row[0], 03772 " CHECK OPTION", NullS) - ptr); 03773 replace(&ds_view, search_buf, search_len, replace_buf, replace_len); 03774 } 03775 03776 /* 03777 "DEFINER=%s SQL SECURITY %s" is available from 5.0.13 03778 Surround it with !50013 comments 03779 */ 03780 { 03781 uint user_name_len; 03782 char user_name_str[USERNAME_LENGTH + 1]; 03783 char quoted_user_name_str[USERNAME_LENGTH * 2 + 3]; 03784 uint host_name_len; 03785 char host_name_str[HOSTNAME_LENGTH + 1]; 03786 char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3]; 03787 03788 parse_user(row[1], lengths[1], user_name_str, &user_name_len, 03789 host_name_str, &host_name_len); 03790 03791 ptr= search_buf; 03792 search_len= 03793 (ulong)(strxmov(ptr, "DEFINER=", 03794 quote_name(user_name_str, quoted_user_name_str, FALSE), 03795 "@", 03796 quote_name(host_name_str, quoted_host_name_str, FALSE), 03797 " SQL SECURITY ", row[2], NullS) - ptr); 03798 ptr= replace_buf; 03799 replace_len= 03800 (ulong)(strxmov(ptr, "*/\n/*!50013 DEFINER=", 03801 quote_name(user_name_str, quoted_user_name_str, FALSE), 03802 "@", 03803 quote_name(host_name_str, quoted_host_name_str, FALSE), 03804 " SQL SECURITY ", row[2], 03805 " */\n/*!50001", NullS) - ptr); 03806 replace(&ds_view, search_buf, search_len, replace_buf, replace_len); 03807 } 03808 03809 /* Dump view structure to file */ 03810 fprintf(sql_file, "/*!50001 %s */;\n", ds_view.str); 03811 check_io(sql_file); 03812 mysql_free_result(table_res); 03813 dynstr_free(&ds_view); 03814 } 03815 03816 /* If a separate .sql file was opened, close it now */ 03817 if (sql_file != md_result_file) 03818 { 03819 fputs("\n", sql_file); 03820 write_footer(sql_file); 03821 my_fclose(sql_file, MYF(MY_WME)); 03822 } 03823 DBUG_RETURN(0); 03824 } 03825 03826 03827 int main(int argc, char **argv) 03828 { 03829 MY_INIT("mysqldump"); 03830 03831 compatible_mode_normal_str[0]= 0; 03832 default_charset= (char *)mysql_universal_client_charset; 03833 bzero((char*) &ignore_table, sizeof(ignore_table)); 03834 03835 if (get_options(&argc, &argv)) 03836 { 03837 my_end(0); 03838 exit(EX_USAGE); 03839 } 03840 if (dbConnect(current_host, current_user, opt_password)) 03841 exit(EX_MYSQLERR); 03842 if (!path) 03843 write_header(md_result_file, *argv); 03844 03845 if ((opt_lock_all_tables || opt_master_data) && 03846 do_flush_tables_read_lock(mysql)) 03847 goto err; 03848 if (opt_single_transaction && start_transaction(mysql, test(opt_master_data))) 03849 goto err; 03850 if (opt_delete_master_logs && do_reset_master(mysql)) 03851 goto err; 03852 if (opt_lock_all_tables || opt_master_data) 03853 { 03854 if (flush_logs && mysql_refresh(mysql, REFRESH_LOG)) 03855 goto err; 03856 flush_logs= 0; /* not anymore; that would not be sensible */ 03857 } 03858 if (opt_master_data && do_show_master_status(mysql)) 03859 goto err; 03860 if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */ 03861 goto err; 03862 03863 if (opt_alltspcs) 03864 dump_all_tablespaces(); 03865 03866 if (opt_alldbs) 03867 dump_all_databases(); 03868 else if (argc > 1 && !opt_databases) 03869 { 03870 /* Only one database and selected table(s) */ 03871 dump_selected_tables(*argv, (argv + 1), (argc - 1)); 03872 } 03873 else 03874 { 03875 /* One or more databases, all tables */ 03876 dump_databases(argv); 03877 } 03878 #ifdef HAVE_SMEM 03879 my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); 03880 #endif 03881 /* 03882 No reason to explicitely COMMIT the transaction, neither to explicitely 03883 UNLOCK TABLES: these will be automatically be done by the server when we 03884 disconnect now. Saves some code here, some network trips, adds nothing to 03885 server. 03886 */ 03887 err: 03888 dbDisconnect(current_host); 03889 if (!path) 03890 write_footer(md_result_file); 03891 if (md_result_file != stdout) 03892 my_fclose(md_result_file, MYF(0)); 03893 my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); 03894 if (hash_inited(&ignore_table)) 03895 hash_free(&ignore_table); 03896 if (extended_insert) 03897 dynstr_free(&extended_row); 03898 if (insert_pat_inited) 03899 dynstr_free(&insert_pat); 03900 my_end(0); 03901 return(first_error); 03902 } /* main */
1.4.7

