mysqldump.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:82k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* mysqldump.c  - Dump a tables contents and format to an ASCII file
  14. **
  15. ** The author's original notes follow :-
  16. **
  17. ** AUTHOR: Igor Romanenko (igor@frog.kiev.ua)
  18. ** DATE:   December 3, 1994
  19. ** WARRANTY: None, expressed, impressed, implied
  20. **     or other
  21. ** STATUS: Public domain
  22. ** Adapted and optimized for MySQL by
  23. ** Michael Widenius, Sinisa Milivojevic, Jani Tolonen
  24. ** -w --where added 9/10/98 by Jim Faucette
  25. ** slave code by David Saez Padros <david@ols.es>
  26. ** master/autocommit code by Brian Aker <brian@tangent.org>
  27. ** SSL by
  28. ** Andrei Errapart <andreie@no.spam.ee>
  29. ** Tõnu Samuel  <tonu@please.do.not.remove.this.spam.ee>
  30. ** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up
  31. ** and adapted to mysqldump 05/11/01 by Jani Tolonen
  32. ** Added --single-transaction option 06/06/2002 by Peter Zaitsev
  33. ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
  34. */
  35. #define DUMP_VERSION "10.9"
  36. #include <my_global.h>
  37. #include <my_sys.h>
  38. #include <m_string.h>
  39. #include <m_ctype.h>
  40. #include <hash.h>
  41. #include "client_priv.h"
  42. #include "mysql.h"
  43. #include "mysql_version.h"
  44. #include "mysqld_error.h"
  45. /* Exit codes */
  46. #define EX_USAGE 1
  47. #define EX_MYSQLERR 2
  48. #define EX_CONSCHECK 3
  49. #define EX_EOM 4
  50. #define EX_EOF 5 /* ferror for output file was got */
  51. #define EX_ILLEGAL_TABLE 6
  52. /* index into 'show fields from table' */
  53. #define SHOW_FIELDNAME  0
  54. #define SHOW_TYPE  1
  55. #define SHOW_NULL  2
  56. #define SHOW_DEFAULT  4
  57. #define SHOW_EXTRA  5
  58. /* Size of buffer for dump's select query */
  59. #define QUERY_LENGTH 1536
  60. static char *add_load_option(char *ptr, const char *object,
  61.      const char *statement);
  62. static ulong find_set(TYPELIB *lib, const char *x, uint length,
  63.       char **err_pos, uint *err_len);
  64. static char *field_escape(char *to,const char *from,uint length);
  65. static my_bool  verbose=0,tFlag=0,dFlag=0,quick= 1, extended_insert= 1,
  66. lock_tables=1,ignore_errors=0,flush_logs=0,
  67. opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
  68.                 opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
  69.                 opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,
  70.                 opt_set_charset=0,
  71. opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
  72. opt_delete_master_logs=0, tty_password=0,
  73. opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
  74. opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
  75.                 opt_complete_insert= 0, opt_drop_database= 0;
  76. static ulong opt_max_allowed_packet, opt_net_buffer_length;
  77. static MYSQL mysql_connection,*sock=0;
  78. static my_bool insert_pat_inited=0;
  79. static DYNAMIC_STRING insert_pat;
  80. static char  *opt_password=0,*current_user=0,
  81.              *current_host=0,*path=0,*fields_terminated=0,
  82.              *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
  83.              *where=0, *order_by=0,
  84.              *opt_compatible_mode_str= 0,
  85.              *err_ptr= 0;
  86. static char compatible_mode_normal_str[255];
  87. static ulong opt_compatible_mode= 0;
  88. #define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
  89. #define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
  90. static uint     opt_mysql_port= 0, err_len= 0, opt_master_data;
  91. static my_string opt_mysql_unix_port=0;
  92. static int   first_error=0;
  93. static DYNAMIC_STRING extended_row;
  94. #include <sslopt-vars.h>
  95. FILE  *md_result_file;
  96. #ifdef HAVE_SMEM
  97. static char *shared_memory_base_name=0;
  98. #endif
  99. static uint opt_protocol= 0;
  100. /*
  101.   Constant for detection of default value of default_charset.
  102.   If default_charset is equal to mysql_universal_client_charset, then
  103.   it is the default value which assigned at the very beginning of main().
  104. */
  105. static const char *mysql_universal_client_charset=
  106.   MYSQL_UNIVERSAL_CLIENT_CHARSET;
  107. static char *default_charset;
  108. static CHARSET_INFO *charset_info= &my_charset_latin1;
  109. const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace";
  110. const char *compatible_mode_names[]=
  111. {
  112.   "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
  113.   "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
  114.   "ANSI",
  115.   NullS
  116. };
  117. #define MASK_ANSI_QUOTES 
  118. (
  119.  (1<<2)  | /* POSTGRESQL */
  120.  (1<<3)  | /* ORACLE     */
  121.  (1<<4)  | /* MSSQL      */
  122.  (1<<5)  | /* DB2        */
  123.  (1<<6)  | /* MAXDB      */
  124.  (1<<10)   /* ANSI       */
  125. )
  126. TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
  127.   "", compatible_mode_names, NULL};
  128. HASH ignore_table;
  129. static struct my_option my_long_options[] =
  130. {
  131.   {"all", 'a', "Deprecated. Use --create-options instead.",
  132.    (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
  133.    0, 0, 0, 0, 0},
  134.   {"all-databases", 'A',
  135.    "Dump all the databases. This will be same as --databases with all databases selected.",
  136.    (gptr*) &opt_alldbs, (gptr*) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
  137.    0, 0},
  138.   {"add-drop-database", OPT_DROP_DATABASE, "Add a 'DROP DATABASE' before each create.",
  139.    (gptr*) &opt_drop_database, (gptr*) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
  140.    0},
  141.   {"add-drop-table", OPT_DROP, "Add a 'drop table' before each create.",
  142.    (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
  143.    0},
  144.   {"add-locks", OPT_LOCKS, "Add locks around insert statements.",
  145.    (gptr*) &opt_lock, (gptr*) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
  146.    0},
  147.   {"allow-keywords", OPT_KEYWORDS,
  148.    "Allow creation of column names that are keywords.", (gptr*) &opt_keywords,
  149.    (gptr*) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  150. #ifdef __NETWARE__
  151.   {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
  152.    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  153. #endif
  154.   {"character-sets-dir", OPT_CHARSETS_DIR,
  155.    "Directory where character sets are.", (gptr*) &charsets_dir,
  156.    (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  157.   {"comments", 'i', "Write additional information.",
  158.    (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
  159.    1, 0, 0, 0, 0, 0},
  160.   {"compatible", OPT_COMPATIBLE,
  161.    "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.",
  162.    (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0,
  163.    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  164.   {"compact", OPT_COMPACT,
  165.    "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",
  166.    (gptr*) &opt_compact, (gptr*) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
  167.    0, 0},
  168.   {"complete-insert", 'c', "Use complete insert statements.",
  169.    (gptr*) &opt_complete_insert, (gptr*) &opt_complete_insert, 0, GET_BOOL,
  170.    NO_ARG, 0, 0, 0, 0, 0, 0},
  171.   {"compress", 'C', "Use compression in server/client protocol.",
  172.    (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
  173.    0, 0, 0},
  174.   {"create-options", OPT_CREATE_OPTIONS,
  175.    "Include all MySQL specific create options.",
  176.    (gptr*) &create_options, (gptr*) &create_options, 0, GET_BOOL, NO_ARG, 1,
  177.    0, 0, 0, 0, 0},
  178.   {"databases", 'B',
  179.    "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.",
  180.    (gptr*) &opt_databases, (gptr*) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0,
  181.    0, 0, 0, 0},
  182. #ifdef DBUG_OFF
  183.   {"debug", '#', "This is a non-debug version. Catch this and exit",
  184.    0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
  185. #else
  186.   {"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
  187.    (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
  188. #endif
  189.   {"default-character-set", OPT_DEFAULT_CHARSET,
  190.    "Set the default character set.", (gptr*) &default_charset,
  191.    (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  192.   {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED.",
  193.    (gptr*) &opt_delayed, (gptr*) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
  194.    0, 0},
  195.   {"delete-master-logs", OPT_DELETE_MASTER_LOGS,
  196.    "Delete logs on master after backup. This automatically enables --master-data.",
  197.    (gptr*) &opt_delete_master_logs, (gptr*) &opt_delete_master_logs, 0,
  198.    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  199.   {"disable-keys", 'K',
  200.    "'/*!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,
  201.    (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
  202.   {"extended-insert", 'e',
  203.    "Allows utilization of the new, much faster INSERT syntax.",
  204.    (gptr*) &extended_insert, (gptr*) &extended_insert, 0, GET_BOOL, NO_ARG,
  205.    1, 0, 0, 0, 0, 0},
  206.   {"fields-terminated-by", OPT_FTB,
  207.    "Fields in the textfile are terminated by ...", (gptr*) &fields_terminated,
  208.    (gptr*) &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  209.   {"fields-enclosed-by", OPT_ENC,
  210.    "Fields in the importfile are enclosed by ...", (gptr*) &enclosed,
  211.    (gptr*) &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
  212.   {"fields-optionally-enclosed-by", OPT_O_ENC,
  213.    "Fields in the i.file are opt. enclosed by ...", (gptr*) &opt_enclosed,
  214.    (gptr*) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
  215.   {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
  216.    (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  217.   {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
  218.    (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
  219.    0, 0, 0, 0, 0, 0},
  220.   {"flush-logs", 'F', "Flush logs file in server before starting dump. "
  221.    "Note that if you dump many databases at once (using the option "
  222.    "--databases= or --all-databases), the logs will be flushed for "
  223.    "each database dumped. The exception is when using --lock-all-tables "
  224.    "or --master-data: "
  225.    "in this case the logs will be flushed only once, corresponding "
  226.    "to the moment all tables are locked. So if you want your dump and "
  227.    "the log flush to happen at the same exact moment you should use "
  228.    "--lock-all-tables or --master-data with --flush-logs",
  229.    (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
  230.    0, 0},
  231.   {"force", 'f', "Continue even if we get an sql-error.",
  232.    (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG,
  233.    0, 0, 0, 0, 0, 0},
  234.   {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
  235.    NO_ARG, 0, 0, 0, 0, 0, 0},
  236.   {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
  237.     "VARBINARY, BLOB) in hexadecimal format.",
  238.    (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  239.   {"host", 'h', "Connect to host.", (gptr*) &current_host,
  240.    (gptr*) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  241.   {"ignore-table", OPT_IGNORE_TABLE,
  242.    "Do not dump the specified table. To specify more than one table to ignore, "
  243.    "use the directive multiple times, once for each table.  Each table must "
  244.    "be specified with both database and table names, e.g. --ignore-table=database.table",
  245.    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  246.   {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
  247.    (gptr*) &opt_ignore, (gptr*) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
  248.    0, 0},
  249.   {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
  250.    (gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR,
  251.    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  252.   {"lock-all-tables", 'x', "Locks all tables across all databases. This " 
  253.    "is achieved by taking a global read lock for the duration of the whole "
  254.    "dump. Automatically turns --single-transaction and --lock-tables off.",
  255.    (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
  256.    0, 0, 0, 0, 0, 0},
  257.   {"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables,
  258.    (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
  259.   {"master-data", OPT_MASTER_DATA,
  260.    "This causes the binary log position and filename to be appended to the "
  261.    "output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
  262.    " to 2, that command will be prefixed with a comment symbol. "
  263.    "This option will turn --lock-all-tables on, unless "
  264.    "--single-transaction is specified too (in which case a "
  265.    "global read lock is only taken a short time at the beginning of the dump "
  266.    "- don't forget to read about --single-transaction below). In all cases "
  267.    "any action on logs will happen at the exact moment of the dump."
  268.    "Option automatically turns --lock-tables off.",
  269.    (gptr*) &opt_master_data, (gptr*) &opt_master_data, 0,
  270.    GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
  271.   {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
  272.     (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0,
  273.     GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096, 
  274.    (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
  275.   {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
  276.     (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0,
  277.     GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
  278.    MALLOC_OVERHEAD-1024, 1024, 0},
  279.   {"no-autocommit", OPT_AUTOCOMMIT,
  280.    "Wrap tables with autocommit/commit statements.",
  281.    (gptr*) &opt_autocommit, (gptr*) &opt_autocommit, 0, GET_BOOL, NO_ARG,
  282.    0, 0, 0, 0, 0, 0},
  283.   {"no-create-db", 'n',
  284.    "'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.}.",
  285.    (gptr*) &opt_create_db, (gptr*) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
  286.    0, 0, 0, 0},
  287.   {"no-create-info", 't', "Don't write table creation info.",
  288.    (gptr*) &tFlag, (gptr*) &tFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  289.   {"no-data", 'd', "No row information.", (gptr*) &dFlag, (gptr*) &dFlag, 0,
  290.    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  291.   {"no-set-names", 'N',
  292.    "Deprecated. Use --skip-set-charset instead.",
  293.    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  294.   {"opt", OPT_OPTIMIZE,
  295.    "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.",
  296.    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  297.   {"order-by-primary", OPT_ORDER_BY_PRIMARY,
  298.    "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.",
  299.    (gptr*) &opt_order_by_primary, (gptr*) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  300.   {"password", 'p',
  301.    "Password to use when connecting to server. If password is not given it's solicited on the tty.",
  302.    0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
  303. #ifdef __WIN__
  304.   {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
  305.    NO_ARG, 0, 0, 0, 0, 0, 0},
  306. #endif
  307.   {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
  308.    (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
  309.    0},
  310.   {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
  311.    0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  312.   {"quick", 'q', "Don't buffer query, dump directly to stdout.",
  313.    (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
  314.   {"quote-names",'Q', "Quote table and column names with backticks (`).",
  315.    (gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
  316.    0, 0},
  317.   {"result-file", 'r',
  318.    "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).",
  319.    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  320.   {"set-charset", OPT_SET_CHARSET,
  321.    "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
  322.    (gptr*) &opt_set_charset, (gptr*) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
  323.    0, 0, 0, 0, 0},
  324.   {"set-variable", 'O',
  325.    "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
  326.    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  327. #ifdef HAVE_SMEM
  328.   {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
  329.    "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
  330.    0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  331. #endif
  332.   /*
  333.     Note that the combination --single-transaction --master-data
  334.     will give bullet-proof binlog position only if server >=4.1.3. That's the
  335.     old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug.
  336.   */
  337.   {"single-transaction", OPT_TRANSACTION,
  338.    "Creates a consistent snapshot by dumping all tables in a single "
  339.    "transaction. Works ONLY for tables stored in storage engines which "
  340.    "support multiversioning (currently only InnoDB does); the dump is NOT "
  341.    "guaranteed to be consistent for other storage engines. Option "
  342.    "automatically turns off --lock-tables.",
  343.    (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0,
  344.    GET_BOOL, NO_ARG,  0, 0, 0, 0, 0, 0},
  345.   {"skip-opt", OPT_SKIP_OPTIMIZATION,
  346.    "Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
  347.    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  348.   {"socket", 'S', "Socket file to use for connection.",
  349.    (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
  350.    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  351. #include <sslopt-longopts.h>
  352.   {"tab",'T',
  353.    "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.",
  354.    (gptr*) &path, (gptr*) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  355.   {"tables", OPT_TABLES, "Overrides option --databases (-B).",
  356.    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  357. #ifndef DONT_ALLOW_USER_CHANGE
  358.   {"user", 'u', "User for login if not current user.",
  359.    (gptr*) &current_user, (gptr*) &current_user, 0, GET_STR, REQUIRED_ARG,
  360.    0, 0, 0, 0, 0, 0},
  361. #endif
  362.   {"verbose", 'v', "Print info about the various stages.",
  363.    (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  364.   {"version",'V', "Output version information and exit.", 0, 0, 0,
  365.    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  366.   {"where", 'w', "Dump only selected records; QUOTES mandatory!",
  367.    (gptr*) &where, (gptr*) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  368.   {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
  369.    NO_ARG, 0, 0, 0, 0, 0, 0},
  370.   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
  371. };
  372. static const char *load_default_groups[]= { "mysqldump","client",0 };
  373. static void safe_exit(int error);
  374. static void write_header(FILE *sql_file, char *db_name);
  375. static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
  376. const char *prefix,const char *name,
  377. int string_value);
  378. static int dump_selected_tables(char *db, char **table_names, int tables);
  379. static int dump_all_tables_in_db(char *db);
  380. static int init_dumping(char *);
  381. static int dump_databases(char **);
  382. static int dump_all_databases();
  383. static char *quote_name(const char *name, char *buff, my_bool force);
  384. static const char *check_if_ignore_table(const char *table_name);
  385. static char *primary_key_fields(const char *table_name);
  386. #include <help_start.h>
  387. /*
  388.   exit with message if ferror(file)
  389.   
  390.   SYNOPSIS
  391.     check_io()
  392.     file - checked file
  393. */
  394. void check_io(FILE *file)
  395. {
  396.   if (ferror(file))
  397.   {
  398.     fprintf(stderr, "%s: Got errno %d on writen", my_progname, errno);
  399.     safe_exit(EX_EOF);
  400.   }
  401. }
  402. static void print_version(void)
  403. {
  404.   printf("%s  Ver %s Distrib %s, for %s (%s)n",my_progname,DUMP_VERSION,
  405.          MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
  406.   NETWARE_SET_SCREEN_MODE(1);
  407. } /* print_version */
  408. static void short_usage_sub(void)
  409. {
  410.   printf("Usage: %s [OPTIONS] database [tables]n", my_progname);
  411.   printf("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]n",
  412.  my_progname);
  413.   printf("OR     %s [OPTIONS] --all-databases [OPTIONS]n", my_progname);
  414.   NETWARE_SET_SCREEN_MODE(1);
  415. }
  416. static void usage(void)
  417. {
  418.   print_version();
  419.   puts("By Igor Romanenko, Monty, Jani & Sinisa");
  420.   puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,nand you are welcome to modify and redistribute it under the GPL licensen");
  421.   puts("Dumping definition and data mysql database or table");
  422.   short_usage_sub();
  423.   print_defaults("my",load_default_groups);
  424.   my_print_help(my_long_options);
  425.   my_print_variables(my_long_options);
  426. } /* usage */
  427. static void short_usage(void)
  428. {
  429.   short_usage_sub();
  430.   printf("For more options, use %s --helpn", my_progname);
  431. }
  432. #include <help_end.h>
  433. static void write_header(FILE *sql_file, char *db_name)
  434. {
  435.   if (opt_xml)
  436.   {
  437.     fputs("<?xml version="1.0"?>n", sql_file);
  438.     fputs("<mysqldump ", sql_file);
  439.     fputs("xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"",
  440.           sql_file);
  441.     fputs(">n", sql_file);
  442.     check_io(sql_file);
  443.   }
  444.   else if (!opt_compact)
  445.   {
  446.     if (opt_comments)
  447.     {
  448.       fprintf(sql_file, "-- MySQL dump %sn--n", DUMP_VERSION);
  449.       fprintf(sql_file, "-- Host: %s    Database: %sn",
  450.       current_host ? current_host : "localhost", db_name ? db_name :
  451.       "");
  452.       fputs("-- ------------------------------------------------------n",
  453.     sql_file);
  454.       fprintf(sql_file, "-- Server versiont%sn",
  455.       mysql_get_server_info(&mysql_connection));
  456.     }
  457.     if (opt_set_charset)
  458.       fprintf(sql_file,
  459. "n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
  460. "n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
  461. "n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
  462. "n/*!40101 SET NAMES %s */;n",default_charset);
  463.     if (!path)
  464.     {
  465.       fprintf(md_result_file,"
  466. /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;n
  467. /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;n
  468. ");
  469.     }
  470.     fprintf(sql_file,
  471.     "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='%s%s%s' */;n"
  472.     "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;n",
  473.     path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",",
  474.     compatible_mode_normal_str);
  475.     check_io(sql_file);
  476.   }
  477. } /* write_header */
  478. static void write_footer(FILE *sql_file)
  479. {
  480.   if (opt_xml)
  481.   {
  482.     fputs("</mysqldump>n", sql_file);
  483.     check_io(sql_file);
  484.   }
  485.   else if (!opt_compact)
  486.   {
  487.     fprintf(sql_file,"n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;n");
  488.     if (!path)
  489.     {
  490.       fprintf(md_result_file,"
  491. /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;n
  492. /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;n");
  493.     }
  494.     if (opt_set_charset)
  495.       fprintf(sql_file,
  496. "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;n"
  497. "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;n"
  498. "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;n");
  499.     fprintf(sql_file,
  500.     "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;n");
  501.     fputs("n", sql_file);
  502.     check_io(sql_file);
  503.   }
  504. } /* write_footer */
  505. static void free_table_ent(char *key)
  506. {
  507.   my_free((gptr) key, MYF(0));
  508. }
  509. byte* get_table_key(const char *entry, uint *length,
  510. my_bool not_used __attribute__((unused)))
  511. {
  512.   *length= strlen(entry);
  513.   return (byte*) entry;
  514. }
  515. void init_table_rule_hash(HASH* h)
  516. {
  517.   if (hash_init(h, charset_info, 16, 0, 0,
  518.                 (hash_get_key) get_table_key,
  519.                 (hash_free_key) free_table_ent, 0))
  520.     exit(EX_EOM);
  521. }
  522. static my_bool
  523. get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
  524.        char *argument)
  525. {
  526.   switch (optid) {
  527. #ifdef __NETWARE__
  528.   case OPT_AUTO_CLOSE:
  529.     setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
  530.     break;
  531. #endif
  532.   case 'p':
  533.     if (argument)
  534.     {
  535.       char *start=argument;
  536.       my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
  537.       opt_password=my_strdup(argument,MYF(MY_FAE));
  538.       while (*argument) *argument++= 'x'; /* Destroy argument */
  539.       if (*start)
  540. start[1]=0; /* Cut length of argument */
  541.       tty_password= 0;
  542.     }
  543.     else
  544.       tty_password=1;
  545.     break;
  546.   case 'r':
  547.     if (!(md_result_file = my_fopen(argument, O_WRONLY | FILE_BINARY,
  548.     MYF(MY_WME))))
  549.       exit(1);
  550.     break;
  551.   case 'W':
  552. #ifdef __WIN__
  553.     opt_protocol = MYSQL_PROTOCOL_PIPE;
  554. #endif
  555.     break;
  556.   case 'N':
  557.     opt_set_charset= 0;
  558.     break;
  559.   case 'T':
  560.     opt_disable_keys=0;
  561.     break;
  562.   case '#':
  563.     DBUG_PUSH(argument ? argument : default_dbug_option);
  564.     break;
  565. #include <sslopt-case.h>
  566.   case 'V': print_version(); exit(0);
  567.   case 'X':
  568.     opt_xml = 1;
  569.     extended_insert= opt_drop= opt_lock= 
  570.       opt_disable_keys= opt_autocommit= opt_create_db= 0;
  571.     break;
  572.   case 'I':
  573.   case '?':
  574.     usage();
  575.     exit(0);
  576.   case (int) OPT_MASTER_DATA:
  577.     if (!argument) /* work like in old versions */
  578.       opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
  579.     break;
  580.   case (int) OPT_OPTIMIZE:
  581.     extended_insert= opt_drop= opt_lock= quick= create_options=
  582.       opt_disable_keys= lock_tables= opt_set_charset= 1;
  583.     break;
  584.   case (int) OPT_SKIP_OPTIMIZATION:
  585.     extended_insert= opt_drop= opt_lock= quick= create_options=
  586.       opt_disable_keys= lock_tables= opt_set_charset= 0;
  587.     break;
  588.   case (int) OPT_COMPACT:
  589.   if (opt_compact)
  590.   {
  591.     opt_comments= opt_drop= opt_disable_keys= opt_lock= 0;
  592.     opt_set_charset= 0;
  593.   }
  594.   case (int) OPT_TABLES:
  595.     opt_databases=0;
  596.     break;
  597.   case (int) OPT_IGNORE_TABLE:
  598.   {
  599.     if (!strchr(argument, '.'))
  600.     {
  601.       fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>n");
  602.       exit(1);
  603.     }
  604.     if (!hash_inited(&ignore_table))
  605.       init_table_rule_hash(&ignore_table);
  606.     if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0))))
  607.       exit(EX_EOM);
  608.     break;
  609.   }
  610.   case (int) OPT_COMPATIBLE:
  611.     {
  612.       char buff[255];
  613.       char *end= compatible_mode_normal_str;
  614.       int i;
  615.       ulong mode;
  616.       opt_quoted= 1;
  617.       opt_set_charset= 0;
  618.       opt_compatible_mode_str= argument;
  619.       opt_compatible_mode= find_set(&compatible_mode_typelib,
  620.     argument, strlen(argument),
  621.     &err_ptr, &err_len);
  622.       if (err_len)
  623.       {
  624. strmake(buff, err_ptr, min(sizeof(buff), err_len));
  625. fprintf(stderr, "Invalid mode to --compatible: %sn", buff);
  626. exit(1);
  627.       }
  628. #if !defined(DBUG_OFF)
  629.       {
  630. uint size_for_sql_mode= 0;
  631. const char **ptr;
  632. for (ptr= compatible_mode_names; *ptr; ptr++)
  633.   size_for_sql_mode+= strlen(*ptr);
  634. size_for_sql_mode+= sizeof(compatible_mode_names)-1;
  635. DBUG_ASSERT(sizeof(compatible_mode_normal_str)>=size_for_sql_mode);
  636.       }
  637. #endif
  638.       mode= opt_compatible_mode;
  639.       for (i= 0, mode= opt_compatible_mode; mode; mode>>= 1, i++)
  640.       {
  641. if (mode & 1)
  642. {
  643.   end= strmov(end, compatible_mode_names[i]);
  644.   end= strmov(end, ",");
  645. }
  646.       }
  647.       if (end!=compatible_mode_normal_str)
  648. end[-1]= 0;
  649.       /* 
  650.         Set charset to the default compiled value if it hasn't
  651.         been reset yet by --default-character-set=xxx.
  652.       */
  653.       if (default_charset == mysql_universal_client_charset)
  654.         default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
  655.       break;
  656.     }
  657.   case (int) OPT_MYSQL_PROTOCOL:
  658.     {
  659.       if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0)
  660.       {
  661. fprintf(stderr, "Unknown option to protocol: %sn", argument);
  662. exit(1);
  663.       }
  664.       break;
  665.     }
  666.   }
  667.   return 0;
  668. }
  669. static int get_options(int *argc, char ***argv)
  670. {
  671.   int ho_error;
  672.   MYSQL_PARAMETERS *mysql_params= mysql_get_parameters();
  673.   opt_max_allowed_packet= *mysql_params->p_max_allowed_packet;
  674.   opt_net_buffer_length= *mysql_params->p_net_buffer_length;
  675.   md_result_file= stdout;
  676.   load_defaults("my",load_default_groups,argc,argv);
  677.   if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
  678.     exit(ho_error);
  679.   *mysql_params->p_max_allowed_packet= opt_max_allowed_packet;
  680.   *mysql_params->p_net_buffer_length= opt_net_buffer_length;
  681.   if (opt_delayed)
  682.     opt_lock=0; /* Can't have lock with delayed */
  683.   if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
  684. fields_terminated))
  685.   {
  686.     fprintf(stderr,
  687.     "%s: You must use option --tab with --fields-...n", my_progname);
  688.     return(1);
  689.   }
  690.   /* Ensure consistency of the set of binlog & locking options */
  691.   if (opt_delete_master_logs && !opt_master_data)
  692.     opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL;
  693.   if (opt_single_transaction && opt_lock_all_tables)
  694.   {
  695.     fprintf(stderr, "%s: You can't use --single-transaction and "
  696.             "--lock-all-tables at the same time.n", my_progname);
  697.     return(1);
  698.   }  
  699.   if (opt_master_data)
  700.     opt_lock_all_tables= !opt_single_transaction;
  701.   if (opt_single_transaction || opt_lock_all_tables)
  702.     lock_tables= 0;
  703.   if (enclosed && opt_enclosed)
  704.   {
  705.     fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.n", my_progname);
  706.     return(1);
  707.   }
  708.   if ((opt_databases || opt_alldbs) && path)
  709.   {
  710.     fprintf(stderr,
  711.     "%s: --databases or --all-databases can't be used with --tab.n",
  712.     my_progname);
  713.     return(1);
  714.   }
  715.   if (strcmp(default_charset, charset_info->csname) &&
  716.       !(charset_info= get_charset_by_csname(default_charset, 
  717.        MY_CS_PRIMARY, MYF(MY_WME))))
  718.     exit(1);
  719.   if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
  720.   {
  721.     short_usage();
  722.     return 1;
  723.   }
  724.   if (tty_password)
  725.     opt_password=get_tty_password(NullS);
  726.   return(0);
  727. } /* get_options */
  728. /*
  729. ** DBerror -- prints mysql error message and exits the program.
  730. */
  731. static void DBerror(MYSQL *mysql, const char *when)
  732. {
  733.   DBUG_ENTER("DBerror");
  734.   my_printf_error(0,"Got error: %d: %s %s", MYF(0),
  735.   mysql_errno(mysql), mysql_error(mysql), when);
  736.   safe_exit(EX_MYSQLERR);
  737.   DBUG_VOID_RETURN;
  738. } /* DBerror */
  739. /*
  740.   Sends a query to server, optionally reads result, prints error message if
  741.   some.
  742.   SYNOPSIS
  743.     mysql_query_with_error_report()
  744.     mysql_con       connection to use
  745.     res             if non zero, result will be put there with mysql_store_result
  746.     query           query to send to server
  747.   RETURN VALUES
  748.     0               query sending and (if res!=0) result reading went ok
  749.     1               error
  750. */
  751.   
  752. static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res,
  753.                                          const char *query)
  754. {
  755.   if (mysql_query(mysql_con, query) ||
  756.       (res && !((*res)= mysql_store_result(mysql_con))))
  757.   {
  758.     my_printf_error(0, "%s: Couldn't execute '%s': %s (%d)",
  759.                     MYF(0), my_progname, query,
  760.                     mysql_error(mysql_con), mysql_errno(mysql_con));
  761.     return 1;
  762.   }
  763.   return 0;
  764. }
  765. static void safe_exit(int error)
  766. {
  767.   if (!first_error)
  768.     first_error= error;
  769.   if (ignore_errors)
  770.     return;
  771.   if (sock)
  772.     mysql_close(sock);
  773.   exit(error);
  774. }
  775. /* safe_exit */
  776. /*
  777. ** dbConnect -- connects to the host and selects DB.
  778. */
  779. static int dbConnect(char *host, char *user,char *passwd)
  780. {
  781.   char buff[20+FN_REFLEN];
  782.   DBUG_ENTER("dbConnect");
  783.   if (verbose)
  784.   {
  785.     fprintf(stderr, "-- Connecting to %s...n", host ? host : "localhost");
  786.   }
  787.   mysql_init(&mysql_connection);
  788.   if (opt_compress)
  789.     mysql_options(&mysql_connection,MYSQL_OPT_COMPRESS,NullS);
  790. #ifdef HAVE_OPENSSL
  791.   if (opt_use_ssl)
  792.     mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
  793.   opt_ssl_capath, opt_ssl_cipher);
  794. #endif
  795.   if (opt_protocol)
  796.     mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
  797. #ifdef HAVE_SMEM
  798.   if (shared_memory_base_name)
  799.     mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
  800. #endif
  801.   mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
  802.   if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd,
  803.          NULL,opt_mysql_port,opt_mysql_unix_port,
  804.          0)))
  805.   {
  806.     DBerror(&mysql_connection, "when trying to connect");
  807.     return 1;
  808.   }
  809.   /*
  810.     Don't dump SET NAMES with a pre-4.1 server (bug#7997).
  811.   */
  812.   if (mysql_get_server_version(&mysql_connection) < 40100)
  813.     opt_set_charset= 0;
  814.   /*
  815.     As we're going to set SQL_MODE, it would be lost on reconnect, so we
  816.     cannot reconnect.
  817.   */
  818.   sock->reconnect= 0;
  819.   my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */",
  820.       compatible_mode_normal_str);
  821.   if (mysql_query_with_error_report(sock, 0, buff))
  822.   {
  823.     mysql_close(sock);
  824.     safe_exit(EX_MYSQLERR);
  825.     return 1;
  826.   }
  827.   return 0;
  828. } /* dbConnect */
  829. /*
  830. ** dbDisconnect -- disconnects from the host.
  831. */
  832. static void dbDisconnect(char *host)
  833. {
  834.   if (verbose)
  835.     fprintf(stderr, "-- Disconnecting from %s...n", host ? host : "localhost");
  836.   mysql_close(sock);
  837. } /* dbDisconnect */
  838. static void unescape(FILE *file,char *pos,uint length)
  839. {
  840.   char *tmp;
  841.   DBUG_ENTER("unescape");
  842.   if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
  843.   {
  844.     ignore_errors=0; /* Fatal error */
  845.     safe_exit(EX_MYSQLERR); /* Force exit */
  846.   }
  847.   mysql_real_escape_string(&mysql_connection, tmp, pos, length);
  848.   fputc(''', file);
  849.   fputs(tmp, file);
  850.   fputc(''', file);
  851.   check_io(file);
  852.   my_free(tmp, MYF(MY_WME));
  853.   DBUG_VOID_RETURN;
  854. } /* unescape */
  855. static my_bool test_if_special_chars(const char *str)
  856. {
  857. #if MYSQL_VERSION_ID >= 32300
  858.   for ( ; *str ; str++)
  859.     if (!my_isvar(charset_info,*str) && *str != '$')
  860.       return 1;
  861. #endif
  862.   return 0;
  863. } /* test_if_special_chars */
  864. static char *quote_name(const char *name, char *buff, my_bool force)
  865. {
  866.   char *to= buff;
  867.   char qtype= (opt_compatible_mode & MASK_ANSI_QUOTES) ? '"' : '`';
  868.   if (!force && !opt_quoted && !test_if_special_chars(name))
  869.     return (char*) name;
  870.   *to++= qtype;
  871.   while (*name)
  872.   {
  873.     if (*name == qtype)
  874.       *to++= qtype;
  875.     *to++= *name++;
  876.   }
  877.   to[0]= qtype;
  878.   to[1]= 0;
  879.   return buff;
  880. } /* quote_name */
  881. /*
  882.   Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
  883.   SYNOPSIS
  884.     quote_for_like()
  885.     name     name of the table
  886.     buff     quoted name of the table
  887.   DESCRIPTION
  888.     Quote , _, ' and % characters
  889.     Note: Because MySQL uses the C escape syntax in strings
  890.     (for example, 'n' to represent newline), you must double
  891.     any '' that you use in your LIKE  strings. For example, to
  892.     search for 'n', specify it as '\n'. To search for '', specify
  893.     it as '\\' (the backslashes are stripped once by the parser
  894.     and another time when the pattern match is done, leaving a
  895.     single backslash to be matched).
  896.     Example: "t1" => "t\\1"
  897. */
  898. static char *quote_for_like(const char *name, char *buff)
  899. {
  900.   char *to= buff;
  901.   *to++= ''';
  902.   while (*name)
  903.   {
  904.     if (*name == '\')
  905.     {
  906.       *to++='\';
  907.       *to++='\';
  908.       *to++='\';
  909.     }
  910.     else if (*name == ''' || *name == '_'  || *name == '%')
  911.       *to++= '\';
  912.     *to++= *name++;
  913.   }
  914.   to[0]= ''';
  915.   to[1]= 0;
  916.   return buff;
  917. }
  918. /*
  919.   Quote and print a string.
  920.   
  921.   SYNOPSIS
  922.     print_quoted_xml()
  923.     output - output file
  924.     str - string to print
  925.     len - its length
  926.     
  927.   DESCRIPTION
  928.     Quote '<' '>' '&' '"' chars and print a string to the xml_file.
  929. */
  930. static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
  931. {
  932.   const char *end;
  933.   
  934.   for (end= str + len; str != end; str++)
  935.   {
  936.     switch (*str) {
  937.     case '<':
  938.       fputs("&lt;", xml_file);
  939.       break;
  940.     case '>':
  941.       fputs("&gt;", xml_file);
  942.       break;
  943.     case '&':
  944.       fputs("&amp;", xml_file);
  945.       break;
  946.     case '"':
  947.       fputs("&quot;", xml_file);
  948.       break;
  949.     default:
  950.       fputc(*str, xml_file);
  951.       break;
  952.     }
  953.   }
  954.   check_io(xml_file);
  955. }
  956. /*
  957.   Print xml tag with one attribute.
  958.   
  959.   SYNOPSIS
  960.     print_xml_tag1()
  961.     xml_file - output file
  962.     sbeg - line beginning
  963.     stag_atr - tag and attribute
  964.     sval - value of attribute
  965.     send - line ending
  966.     
  967.   DESCRIPTION
  968.     Print tag with one attribute to the xml_file. Format is:
  969.       sbeg<stag_atr="sval">send
  970.   NOTE
  971.     sval MUST be a NULL terminated string.
  972.     sval string will be qouted before output.
  973. */
  974. static void print_xml_tag1(FILE * xml_file, const char* sbeg,
  975.    const char* stag_atr, const char* sval,
  976.    const char* send)
  977. {
  978.   fputs(sbeg, xml_file);
  979.   fputs("<", xml_file);
  980.   fputs(stag_atr, xml_file);
  981.   fputs(""", xml_file);
  982.   print_quoted_xml(xml_file, sval, strlen(sval));
  983.   fputs("">", xml_file);
  984.   fputs(send, xml_file);
  985.   check_io(xml_file);
  986. }
  987. /*
  988.   Print xml tag with for a field that is null
  989.   SYNOPSIS
  990.     print_xml_null_tag()
  991.     xml_file - output file
  992.     sbeg - line beginning
  993.     stag_atr - tag and attribute
  994.     sval - value of attribute
  995.     send - line ending
  996.   DESCRIPTION
  997.     Print tag with one attribute to the xml_file. Format is:
  998.       <stag_atr="sval" xsi:nil="true"/>
  999.   NOTE
  1000.     sval MUST be a NULL terminated string.
  1001.     sval string will be qouted before output.
  1002. */
  1003. static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
  1004.                                const char* stag_atr, const char* sval,
  1005.                                const char* send)
  1006. {
  1007.   fputs(sbeg, xml_file);
  1008.   fputs("<", xml_file);
  1009.   fputs(stag_atr, xml_file);
  1010.   fputs(""", xml_file);
  1011.   print_quoted_xml(xml_file, sval, strlen(sval));
  1012.   fputs("" xsi:nil="true" />", xml_file);
  1013.   fputs(send, xml_file);
  1014.   check_io(xml_file);
  1015. }
  1016. /*
  1017.   Print xml tag with many attributes.
  1018.   SYNOPSIS
  1019.     print_xml_row()
  1020.     xml_file - output file
  1021.     row_name - xml tag name
  1022.     tableRes - query result
  1023.     row - result row
  1024.     
  1025.   DESCRIPTION
  1026.     Print tag with many attribute to the xml_file. Format is:
  1027.       tt<row_name Atr1="Val1" Atr2="Val2"... />
  1028.   NOTE
  1029.     All atributes and values will be quoted before output.
  1030. */
  1031. static void print_xml_row(FILE *xml_file, const char *row_name,
  1032.   MYSQL_RES *tableRes, MYSQL_ROW *row)
  1033. {
  1034.   uint i;
  1035.   MYSQL_FIELD *field;
  1036.   ulong *lengths= mysql_fetch_lengths(tableRes);
  1037.   
  1038.   fprintf(xml_file, "tt<%s", row_name);
  1039.   check_io(xml_file);
  1040.   mysql_field_seek(tableRes, 0);
  1041.   for (i= 0; (field= mysql_fetch_field(tableRes)); i++)
  1042.   {
  1043.     if ((*row)[i])
  1044.     {
  1045.       fputc(' ', xml_file);
  1046.       print_quoted_xml(xml_file, field->name, field->name_length);
  1047.       fputs("="", xml_file);
  1048.       print_quoted_xml(xml_file, (*row)[i], lengths[i]);
  1049.       fputc('"', xml_file);
  1050.       check_io(xml_file);
  1051.     }
  1052.   }
  1053.   fputs(" />n", xml_file);
  1054.   check_io(xml_file);
  1055. }
  1056. /*
  1057.   getTableStructure -- retrievs database structure, prints out corresponding
  1058.   CREATE statement and fills out insert_pat.
  1059.   RETURN
  1060.     number of fields in table, 0 if error
  1061. */
  1062. static uint getTableStructure(char *table, char* db)
  1063. {
  1064.   MYSQL_RES  *tableRes;
  1065.   MYSQL_ROW  row;
  1066.   my_bool    init=0;
  1067.   uint       numFields;
  1068.   char      *result_table, *opt_quoted_table;
  1069.   const char *insert_option;
  1070.   char      name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
  1071.   char      table_buff2[NAME_LEN*2+3];
  1072.   char       query_buff[512];
  1073.   FILE       *sql_file = md_result_file;
  1074.   int        len;
  1075.   DBUG_ENTER("getTableStructure");
  1076.   DBUG_PRINT("enter", ("db: %s, table: %s", db, table));
  1077.   if (!insert_pat_inited)
  1078.   {
  1079.     insert_pat_inited= init_dynamic_string(&insert_pat, "", 1024, 1024);
  1080.   }
  1081.   else
  1082.     dynstr_set(&insert_pat, "");
  1083.   insert_option= ((opt_delayed && opt_ignore) ? " DELAYED IGNORE " : 
  1084.                   opt_delayed ? " DELAYED " :
  1085.                   opt_ignore ? " IGNORE " : "");
  1086.   if (verbose)
  1087.     fprintf(stderr, "-- Retrieving table structure for table %s...n", table);
  1088.   len= my_snprintf(query_buff, sizeof(query_buff),
  1089.                    "SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
  1090.                    (opt_quoted || opt_keywords));
  1091.   if (!create_options)
  1092.     strmov(query_buff+len, "/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */");
  1093.   result_table=     quote_name(table, table_buff, 1);
  1094.   opt_quoted_table= quote_name(table, table_buff2, 0);
  1095.   if (opt_order_by_primary)
  1096.     order_by = primary_key_fields(opt_quoted_table);
  1097.   if (!opt_xml && !mysql_query_with_error_report(sock, 0, query_buff))
  1098.   {
  1099.     /* using SHOW CREATE statement */
  1100.     if (!tFlag)
  1101.     {
  1102.       /* Make an sql-file, if path was given iow. option -T was given */
  1103.       char buff[20+FN_REFLEN];
  1104.       my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
  1105.       if (mysql_query_with_error_report(sock, 0, buff))
  1106.       {
  1107.         safe_exit(EX_MYSQLERR);
  1108.         DBUG_RETURN(0);
  1109.       }
  1110.       if (path)
  1111.       {
  1112.         char filename[FN_REFLEN], tmp_path[FN_REFLEN];
  1113.         convert_dirname(tmp_path,path,NullS);
  1114.         sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
  1115.  O_WRONLY, MYF(MY_WME));
  1116.         if (!sql_file) /* If file couldn't be opened */
  1117.         {
  1118.   safe_exit(EX_MYSQLERR);
  1119.   DBUG_RETURN(0);
  1120.         }
  1121.         write_header(sql_file, db);
  1122.       }
  1123.       if (!opt_xml && opt_comments)
  1124.       {
  1125.         fprintf(sql_file, "n--n-- Table structure for table %sn--nn",
  1126. result_table);
  1127. check_io(sql_file);
  1128.       }
  1129.       if (opt_drop)
  1130.       {
  1131.         fprintf(sql_file, "DROP TABLE IF EXISTS %s;n", opt_quoted_table);
  1132. check_io(sql_file);
  1133.       }
  1134.       tableRes=mysql_store_result(sock);
  1135.       row=mysql_fetch_row(tableRes);
  1136.       fprintf(sql_file, "%s;n", row[1]);
  1137.       check_io(sql_file);
  1138.       mysql_free_result(tableRes);
  1139.     }
  1140.     my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
  1141. result_table);
  1142.     if (mysql_query_with_error_report(sock, &tableRes, query_buff))
  1143.     {
  1144.       if (path)
  1145. my_fclose(sql_file, MYF(MY_WME));
  1146.       safe_exit(EX_MYSQLERR);
  1147.       DBUG_RETURN(0);
  1148.     }
  1149.     dynstr_append_mem(&insert_pat, "INSERT ", 7);
  1150.     dynstr_append(&insert_pat, insert_option);
  1151.     dynstr_append_mem(&insert_pat, "INTO ", 5);
  1152.     dynstr_append(&insert_pat, opt_quoted_table);
  1153.     if (opt_complete_insert)
  1154.     {
  1155.       dynstr_append_mem(&insert_pat, " (", 2);
  1156.     }
  1157.     else
  1158.     {
  1159.       dynstr_append_mem(&insert_pat, " VALUES ", 8);
  1160.       if (!extended_insert)
  1161.         dynstr_append_mem(&insert_pat, "(", 1);
  1162.     }
  1163.     while ((row=mysql_fetch_row(tableRes)))
  1164.     {
  1165.       if (init)
  1166.       {
  1167.         if (opt_complete_insert)
  1168.           dynstr_append_mem(&insert_pat, ", ", 2);
  1169.       }
  1170.       init=1;
  1171.       if (opt_complete_insert)
  1172.         dynstr_append(&insert_pat,
  1173.                       quote_name(row[SHOW_FIELDNAME], name_buff, 0));
  1174.     }
  1175.     numFields = (uint) mysql_num_rows(tableRes);
  1176.     mysql_free_result(tableRes);
  1177.   }
  1178.   else
  1179.   {
  1180.     if (verbose)
  1181.       fprintf(stderr,
  1182.               "%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)n",
  1183.               my_progname, mysql_error(sock));
  1184.     my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
  1185. result_table);
  1186.     if (mysql_query_with_error_report(sock, &tableRes, query_buff))
  1187.     {
  1188.       safe_exit(EX_MYSQLERR);
  1189.       DBUG_RETURN(0);
  1190.     }
  1191.     /* Make an sql-file, if path was given iow. option -T was given */
  1192.     if (!tFlag)
  1193.     {
  1194.       if (path)
  1195.       {
  1196.         char filename[FN_REFLEN], tmp_path[FN_REFLEN];
  1197.         convert_dirname(tmp_path,path,NullS);
  1198.         sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
  1199.  O_WRONLY, MYF(MY_WME));
  1200.         if (!sql_file) /* If file couldn't be opened */
  1201.         {
  1202.   safe_exit(EX_MYSQLERR);
  1203.   DBUG_RETURN(0);
  1204.         }
  1205.         write_header(sql_file, db);
  1206.       }
  1207.       if (!opt_xml && opt_comments)
  1208. fprintf(sql_file, "n--n-- Table structure for table %sn--nn",
  1209. result_table);
  1210.       if (opt_drop)
  1211.         fprintf(sql_file, "DROP TABLE IF EXISTS %s;n",result_table);
  1212.       if (!opt_xml)
  1213. fprintf(sql_file, "CREATE TABLE %s (n", result_table);
  1214.       else
  1215.         print_xml_tag1(sql_file, "t", "table_structure name=", table, "n");
  1216.       check_io(sql_file);
  1217.     }
  1218.     dynstr_append_mem(&insert_pat, "INSERT ", 7);
  1219.     dynstr_append(&insert_pat, insert_option);
  1220.     dynstr_append_mem(&insert_pat, "INTO ", 5);
  1221.     dynstr_append(&insert_pat, result_table);
  1222.     if (opt_complete_insert)
  1223.     {
  1224.       dynstr_append_mem(&insert_pat, " (", 2);
  1225.     }
  1226.     else
  1227.     {
  1228.       dynstr_append_mem(&insert_pat, " VALUES ", 8);
  1229.       if (!extended_insert)
  1230.         dynstr_append_mem(&insert_pat, "(", 1);
  1231.     }
  1232.     while ((row=mysql_fetch_row(tableRes)))
  1233.     {
  1234.       ulong *lengths=mysql_fetch_lengths(tableRes);
  1235.       if (init)
  1236.       {
  1237.         if (!opt_xml && !tFlag)
  1238. {
  1239.   fputs(",n",sql_file);
  1240.   check_io(sql_file);
  1241. }
  1242.         if (opt_complete_insert)
  1243.           dynstr_append_mem(&insert_pat, ", ", 2);
  1244.       }
  1245.       init=1;
  1246.       if (opt_complete_insert)
  1247.         dynstr_append(&insert_pat,
  1248.                       quote_name(row[SHOW_FIELDNAME], name_buff, 0));
  1249.       if (!tFlag)
  1250.       {
  1251. if (opt_xml)
  1252. {
  1253.   print_xml_row(sql_file, "field", tableRes, &row);
  1254.   continue;
  1255. }
  1256.         if (opt_keywords)
  1257.   fprintf(sql_file, "  %s.%s %s", result_table,
  1258.   quote_name(row[SHOW_FIELDNAME],name_buff, 0),
  1259.   row[SHOW_TYPE]);
  1260.         else
  1261.   fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],
  1262.   name_buff, 0),
  1263.   row[SHOW_TYPE]);
  1264.         if (row[SHOW_DEFAULT])
  1265.         {
  1266.   fputs(" DEFAULT ", sql_file);
  1267.   unescape(sql_file, row[SHOW_DEFAULT], lengths[SHOW_DEFAULT]);
  1268.         }
  1269.         if (!row[SHOW_NULL][0])
  1270.   fputs(" NOT NULL", sql_file);
  1271.         if (row[SHOW_EXTRA][0])
  1272.   fprintf(sql_file, " %s",row[SHOW_EXTRA]);
  1273. check_io(sql_file);
  1274.       }
  1275.     }
  1276.     numFields = (uint) mysql_num_rows(tableRes);
  1277.     mysql_free_result(tableRes);
  1278.     if (!tFlag)
  1279.     {
  1280.       /* Make an sql-file, if path was given iow. option -T was given */
  1281.       char buff[20+FN_REFLEN];
  1282.       uint keynr,primary_key;
  1283.       my_snprintf(buff, sizeof(buff), "show keys from %s", result_table);
  1284.       if (mysql_query_with_error_report(sock, &tableRes, buff))
  1285.       {
  1286.         if (path)
  1287.   my_fclose(sql_file, MYF(MY_WME));
  1288.         safe_exit(EX_MYSQLERR);
  1289.         DBUG_RETURN(0);
  1290.       }
  1291.       /* Find first which key is primary key */
  1292.       keynr=0;
  1293.       primary_key=INT_MAX;
  1294.       while ((row=mysql_fetch_row(tableRes)))
  1295.       {
  1296.         if (atoi(row[3]) == 1)
  1297.         {
  1298.   keynr++;
  1299. #ifdef FORCE_PRIMARY_KEY
  1300.   if (atoi(row[1]) == 0 && primary_key == INT_MAX)
  1301.     primary_key=keynr;
  1302. #endif
  1303.   if (!strcmp(row[2],"PRIMARY"))
  1304.   {
  1305.     primary_key=keynr;
  1306.     break;
  1307.   }
  1308.         }
  1309.       }
  1310.       mysql_data_seek(tableRes,0);
  1311.       keynr=0;
  1312.       while ((row=mysql_fetch_row(tableRes)))
  1313.       {
  1314. if (opt_xml)
  1315. {
  1316.   print_xml_row(sql_file, "key", tableRes, &row);
  1317.   continue;
  1318. }
  1319.         
  1320.         if (atoi(row[3]) == 1)
  1321.         {
  1322.   if (keynr++)
  1323.     putc(')', sql_file);
  1324.   if (atoi(row[1]))       /* Test if duplicate key */
  1325.     /* Duplicate allowed */
  1326.     fprintf(sql_file, ",n  KEY %s (",quote_name(row[2],name_buff,0));
  1327.   else if (keynr == primary_key)
  1328.     fputs(",n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
  1329.   else
  1330.     fprintf(sql_file, ",n  UNIQUE %s (",quote_name(row[2],name_buff,
  1331.     0));
  1332.         }
  1333.         else
  1334.   putc(',', sql_file);
  1335.         fputs(quote_name(row[4], name_buff, 0), sql_file);
  1336.         if (row[7])
  1337.   fprintf(sql_file, " (%s)",row[7]);      /* Sub key */
  1338. check_io(sql_file);
  1339.       }
  1340.       if (!opt_xml)
  1341.       {
  1342. if (keynr)
  1343.   putc(')', sql_file);
  1344. fputs("n)",sql_file);
  1345. check_io(sql_file);
  1346.       }
  1347.       /* Get MySQL specific create options */
  1348.       if (create_options)
  1349.       {
  1350. char show_name_buff[FN_REFLEN];
  1351. /* Check memory for quote_for_like() */
  1352. DBUG_ASSERT(2*sizeof(table) < sizeof(show_name_buff));
  1353.         my_snprintf(buff, sizeof(buff), "show table status like %s",
  1354.     quote_for_like(table, show_name_buff));
  1355.         if (mysql_query_with_error_report(sock, &tableRes, buff))
  1356.         {
  1357.   if (mysql_errno(sock) != ER_PARSE_ERROR)
  1358.   { /* If old MySQL version */
  1359.     if (verbose)
  1360.       fprintf(stderr,
  1361.       "-- Warning: Couldn't get status information for table %s (%s)n",
  1362.       result_table,mysql_error(sock));
  1363.   }
  1364.         }
  1365.         else if (!(row=mysql_fetch_row(tableRes)))
  1366.         {
  1367.   fprintf(stderr,
  1368.   "Error: Couldn't read status information for table %s (%s)n",
  1369.   result_table,mysql_error(sock));
  1370.         }
  1371.         else
  1372.         {
  1373.   if (opt_xml)
  1374.   {
  1375.     print_xml_row(sql_file, "options", tableRes, &row);
  1376.   }
  1377.   else
  1378.   {
  1379.     fputs("/*!",sql_file);
  1380.     print_value(sql_file,tableRes,row,"engine=","Engine",0);
  1381.     print_value(sql_file,tableRes,row,"","Create_options",0);
  1382.     print_value(sql_file,tableRes,row,"comment=","Comment",1);
  1383.     fputs(" */",sql_file);
  1384.     check_io(sql_file);
  1385.   }
  1386.         }
  1387.         mysql_free_result(tableRes); /* Is always safe to free */
  1388.       }
  1389.       if (!opt_xml)
  1390. fputs(";n", sql_file);
  1391.       else
  1392. fputs("t</table_structure>n", sql_file);
  1393.       check_io(sql_file);
  1394.     }
  1395.   }
  1396.   if (opt_complete_insert)
  1397.   {
  1398.     dynstr_append_mem(&insert_pat, ") VALUES ", 9);
  1399.     if (!extended_insert)
  1400.       dynstr_append_mem(&insert_pat, "(", 1);
  1401.   }
  1402.   if (sql_file != md_result_file)
  1403.   {
  1404.     fputs("n", sql_file);
  1405.     write_footer(sql_file);
  1406.     my_fclose(sql_file, MYF(MY_WME));
  1407.   }
  1408.   DBUG_RETURN(numFields);
  1409. } /* getTableStructure */
  1410. static char *add_load_option(char *ptr,const char *object,
  1411.      const char *statement)
  1412. {
  1413.   if (object)
  1414.   {
  1415.     /* Don't escape hex constants */
  1416.     if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
  1417.       ptr= strxmov(ptr," ",statement," ",object,NullS);
  1418.     else
  1419.     {
  1420.       /* char constant; escape */
  1421.       ptr= strxmov(ptr," ",statement," '",NullS);
  1422.       ptr= field_escape(ptr,object,(uint) strlen(object));
  1423.       *ptr++= ''';
  1424.     }
  1425.   }
  1426.   return ptr;
  1427. } /* add_load_option */
  1428. /*
  1429. ** Allow the user to specify field terminator strings like:
  1430. ** "'", "", "\" (escaped backslash), "t" (tab), "n" (newline)
  1431. ** This is done by doubleing ' and add a end - if needed to avoid
  1432. ** syntax errors from the SQL parser.
  1433. */
  1434. static char *field_escape(char *to,const char *from,uint length)
  1435. {
  1436.   const char *end;
  1437.   uint end_backslashes=0;
  1438.   for (end= from+length; from != end; from++)
  1439.   {
  1440.     *to++= *from;
  1441.     if (*from == '\')
  1442.       end_backslashes^=1;    /* find odd number of backslashes */
  1443.     else
  1444.     {
  1445.       if (*from == ''' && !end_backslashes)
  1446. *to++= *from;      /* We want a duplicate of "'" for MySQL */
  1447.       end_backslashes=0;
  1448.     }
  1449.   }
  1450.   /* Add missing backslashes if user has specified odd number of backs.*/
  1451.   if (end_backslashes)
  1452.     *to++= '\';
  1453.   return to;
  1454. } /* field_escape */
  1455. static char *alloc_query_str(ulong size)
  1456. {
  1457.   char *query;
  1458.   if (!(query= (char*) my_malloc(size, MYF(MY_WME))))
  1459.   {
  1460.     ignore_errors= 0;    /* Fatal error */
  1461.     safe_exit(EX_MYSQLERR); /* Force exit */
  1462.   }
  1463.   return query;
  1464. }
  1465. /*
  1466. ** dumpTable saves database contents as a series of INSERT statements.
  1467. */
  1468. static void dumpTable(uint numFields, char *table)
  1469. {
  1470.   char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3];
  1471.   char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
  1472.   char *query= query_buf;
  1473.   MYSQL_RES *res;
  1474.   MYSQL_FIELD *field;
  1475.   MYSQL_ROW row;
  1476.   ulong rownr, row_break, total_length, init_length;
  1477.   const char    *table_type;
  1478.   int error= 0;
  1479.   result_table= quote_name(table,table_buff, 1);
  1480.   opt_quoted_table= quote_name(table, table_buff2, 0);
  1481.   /* Check table type */
  1482.   if ((table_type= check_if_ignore_table(table)))
  1483.   {
  1484.     if (verbose)
  1485.       fprintf(stderr,
  1486.       "-- Skipping data for table '%s' because it's of type %sn",
  1487.       table, table_type);
  1488.     return;
  1489.   }
  1490.   if (verbose)
  1491.     fprintf(stderr, "-- Sending SELECT query...n");
  1492.   if (path)
  1493.   {
  1494.     char filename[FN_REFLEN], tmp_path[FN_REFLEN];
  1495.     convert_dirname(tmp_path,path,NullS);
  1496.     my_load_path(tmp_path, tmp_path, NULL);
  1497.     fn_format(filename, table, tmp_path, ".txt", 4);
  1498.     my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if
  1499.     filename wasn't deleted */
  1500.     to_unix_path(filename);
  1501.     my_snprintf(query, QUERY_LENGTH, 
  1502. "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
  1503. filename);
  1504.     end= strend(query);
  1505.     if (fields_terminated || enclosed || opt_enclosed || escaped)
  1506.       end= strmov(end, " FIELDS");
  1507.     end= add_load_option(end, fields_terminated, " TERMINATED BY");
  1508.     end= add_load_option(end, enclosed, " ENCLOSED BY");
  1509.     end= add_load_option(end, opt_enclosed, " OPTIONALLY ENCLOSED BY");
  1510.     end= add_load_option(end, escaped, " ESCAPED BY");
  1511.     end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
  1512.     *end= '';
  1513.     my_snprintf(buff, sizeof(buff), " FROM %s", result_table);
  1514.     end= strmov(end,buff);
  1515.     if (where || order_by)
  1516.     {
  1517.       query = alloc_query_str((ulong) ((end - query) + 1 +
  1518.                              (where ? strlen(where) + 7 : 0) +
  1519.                              (order_by ? strlen(order_by) + 10 : 0)));
  1520.       end = strmov(query, query_buf);
  1521.       if (where)
  1522.         end = strxmov(end, " WHERE ", where, NullS);
  1523.       if (order_by)
  1524.         end = strxmov(end, " ORDER BY ", order_by, NullS);
  1525.     }
  1526.     if (mysql_real_query(sock, query, (uint) (end - query)))
  1527.     {
  1528.       DBerror(sock, "when executing 'SELECT INTO OUTFILE'");
  1529.       return;
  1530.     }
  1531.   }
  1532.   else
  1533.   {
  1534.     if (!opt_xml && opt_comments)
  1535.     {
  1536.       fprintf(md_result_file,"n--n-- Dumping data for table %sn--n",
  1537.       result_table);
  1538.       check_io(md_result_file);
  1539.     }
  1540.     my_snprintf(query, QUERY_LENGTH,
  1541. "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
  1542. result_table);
  1543.     if (where || order_by)
  1544.     {
  1545.       query = alloc_query_str((ulong) (strlen(query) + 1 +
  1546.                              (where ? strlen(where) + 7 : 0) +
  1547.                              (order_by ? strlen(order_by) + 10 : 0)));
  1548.       end = strmov(query, query_buf);
  1549.       if (where)
  1550.       {
  1551.         if (!opt_xml && opt_comments)
  1552.         {
  1553.           fprintf(md_result_file, "-- WHERE:  %sn", where);
  1554.           check_io(md_result_file);
  1555.         }
  1556.         end = strxmov(end, " WHERE ", where, NullS);
  1557.       }
  1558.       if (order_by)
  1559.       {
  1560.         if (!opt_xml && opt_comments)
  1561.         {
  1562.           fprintf(md_result_file, "-- ORDER BY:  %sn", order_by);
  1563.           check_io(md_result_file);
  1564.         }
  1565.         end = strxmov(end, " ORDER BY ", order_by, NullS);
  1566.       }
  1567.     }
  1568.     if (!opt_xml && !opt_compact)
  1569.     {
  1570.       fputs("n", md_result_file);
  1571.       check_io(md_result_file);
  1572.     }
  1573.     if (mysql_query_with_error_report(sock, 0, query))
  1574.       DBerror(sock, "when retrieving data from server");
  1575.     if (quick)
  1576.       res=mysql_use_result(sock);
  1577.     else
  1578.       res=mysql_store_result(sock);
  1579.     if (!res)
  1580.       DBerror(sock, "when retrieving data from server");
  1581.     if (verbose)
  1582.       fprintf(stderr, "-- Retrieving rows...n");
  1583.     if (mysql_num_fields(res) != numFields)
  1584.     {
  1585.       fprintf(stderr,"%s: Error in field count for table: %s !  Aborting.n",
  1586.       my_progname, result_table);
  1587.       error= EX_CONSCHECK;
  1588.       goto err;
  1589.     }
  1590.     if (opt_disable_keys)
  1591.     {
  1592.       fprintf(md_result_file, "n/*!40000 ALTER TABLE %s DISABLE KEYS */;n",
  1593.       opt_quoted_table);
  1594.       check_io(md_result_file);
  1595.     }
  1596.     if (opt_lock)
  1597.     {
  1598.       fprintf(md_result_file,"LOCK TABLES %s WRITE;n", opt_quoted_table);
  1599.       check_io(md_result_file);
  1600.     }
  1601.     total_length= opt_net_buffer_length; /* Force row break */
  1602.     row_break=0;
  1603.     rownr=0;
  1604.     init_length=(uint) insert_pat.length+4;
  1605.     if (opt_xml)
  1606.       print_xml_tag1(md_result_file, "t", "table_data name=", table, "n");
  1607.     if (opt_autocommit)
  1608.     {
  1609.       fprintf(md_result_file, "set autocommit=0;n");
  1610.       check_io(md_result_file);
  1611.     }
  1612.     while ((row=mysql_fetch_row(res)))
  1613.     {
  1614.       uint i;
  1615.       ulong *lengths=mysql_fetch_lengths(res);
  1616.       rownr++;
  1617.       if (!extended_insert && !opt_xml)
  1618.       {
  1619. fputs(insert_pat.str,md_result_file);
  1620. check_io(md_result_file);
  1621.       }
  1622.       mysql_field_seek(res,0);
  1623.       if (opt_xml)
  1624.       {
  1625.         fputs("t<row>n", md_result_file);
  1626. check_io(md_result_file);
  1627.       }
  1628.       for (i = 0; i < mysql_num_fields(res); i++)
  1629.       {
  1630.         int is_blob;
  1631. if (!(field = mysql_fetch_field(res)))
  1632. {
  1633.   my_snprintf(query, QUERY_LENGTH,
  1634.       "%s: Not enough fields from table %s! Aborting.n",
  1635.       my_progname, result_table);
  1636.   fputs(query,stderr);
  1637.   error= EX_CONSCHECK;
  1638.   goto err;
  1639. }
  1640. /*
  1641.    63 is my_charset_bin. If charsetnr is not 63,
  1642.    we have not a BLOB but a TEXT column. 
  1643.    we'll dump in hex only BLOB columns.
  1644. */
  1645.         is_blob= (opt_hex_blob && field->charsetnr == 63 &&
  1646.                   (field->type == FIELD_TYPE_STRING ||
  1647.                    field->type == FIELD_TYPE_VAR_STRING ||
  1648.                    field->type == FIELD_TYPE_BLOB ||
  1649.                    field->type == FIELD_TYPE_LONG_BLOB ||
  1650.                    field->type == FIELD_TYPE_MEDIUM_BLOB ||
  1651.                    field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0;
  1652. if (extended_insert)
  1653. {
  1654.   ulong length = lengths[i];
  1655.   if (i == 0)
  1656.     dynstr_set(&extended_row,"(");
  1657.   else
  1658.     dynstr_append(&extended_row,",");
  1659.   if (row[i])
  1660.   {
  1661.     if (length)
  1662.     {
  1663.       if (!IS_NUM_FIELD(field))
  1664.       {
  1665.         /*
  1666.           "length * 2 + 2" is OK for both HEX and non-HEX modes:
  1667.           - In HEX mode we need exactly 2 bytes per character
  1668.           plus 2 bytes for '0x' prefix.
  1669.           - In non-HEX mode we need up to 2 bytes per character,
  1670.           plus 2 bytes for leading and trailing ''' characters.
  1671.         */
  1672. if (dynstr_realloc(&extended_row,length * 2+2))
  1673. {
  1674.   fputs("Aborting dump (out of memory)",stderr);
  1675.   error= EX_EOM;
  1676.   goto err;
  1677. }
  1678.                 if (opt_hex_blob && is_blob)
  1679.                 {
  1680.                   dynstr_append(&extended_row, "0x");
  1681.                   extended_row.length+= mysql_hex_string(extended_row.str + 
  1682.                                                          extended_row.length,
  1683.                                                          row[i], length);
  1684.                   extended_row.str[extended_row.length]= '';
  1685.                 }
  1686.                 else
  1687.                 {
  1688.                   dynstr_append(&extended_row,"'");
  1689.                   extended_row.length +=
  1690.                   mysql_real_escape_string(&mysql_connection,
  1691.                                            &extended_row.str[extended_row.length],
  1692.                                            row[i],length);
  1693.                   extended_row.str[extended_row.length]='';
  1694.                   dynstr_append(&extended_row,"'");
  1695.                 }
  1696.       }
  1697.       else
  1698.       {
  1699. /* change any strings ("inf", "-inf", "nan") into NULL */
  1700. char *ptr = row[i];
  1701. if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
  1702.     my_isalpha(charset_info, ptr[1])))
  1703.   dynstr_append(&extended_row, "NULL");
  1704. else
  1705. {
  1706.   if (field->type == FIELD_TYPE_DECIMAL)
  1707.   {
  1708.     /* add " signs around */
  1709.     dynstr_append(&extended_row, "'");
  1710.     dynstr_append(&extended_row, ptr);
  1711.     dynstr_append(&extended_row, "'");
  1712.   }
  1713.   else
  1714.     dynstr_append(&extended_row, ptr);
  1715. }
  1716.       }
  1717.     }
  1718.     else
  1719.       dynstr_append(&extended_row,"''");
  1720.   }
  1721.   else if (dynstr_append(&extended_row,"NULL"))
  1722.   {
  1723.     fputs("Aborting dump (out of memory)",stderr);
  1724.     error= EX_EOM;
  1725.     goto err;
  1726.   }
  1727. }
  1728. else
  1729. {
  1730.   if (i && !opt_xml)
  1731.   {
  1732.     fputc(',', md_result_file);
  1733.     check_io(md_result_file);
  1734.   }
  1735.   if (row[i])
  1736.   {
  1737.     if (!IS_NUM_FIELD(field))
  1738.     {
  1739.       if (opt_xml)
  1740.       {
  1741.         print_xml_tag1(md_result_file, "tt", "field name=",
  1742.       field->name, "");
  1743. print_quoted_xml(md_result_file, row[i], lengths[i]);
  1744. fputs("</field>n", md_result_file);
  1745.       }
  1746.       else if (opt_hex_blob && is_blob)
  1747.               {
  1748.                 /* sakaik got the idea to to provide blob's in hex notation. */
  1749.                 char *ptr= row[i], *end= ptr+ lengths[i];
  1750.                 fputs("0x", md_result_file);
  1751.                 for (; ptr < end ; ptr++)
  1752.   fprintf(md_result_file, "%02X", *((uchar *)ptr));
  1753.               }
  1754.               else
  1755.                 unescape(md_result_file, row[i], lengths[i]);
  1756.     }
  1757.     else
  1758.     {
  1759.       /* change any strings ("inf", "-inf", "nan") into NULL */
  1760.       char *ptr = row[i];
  1761.       if (opt_xml)
  1762.       {
  1763.         print_xml_tag1(md_result_file, "tt", "field name=",
  1764.        field->name, "");
  1765. fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
  1766.       md_result_file);
  1767. fputs("</field>n", md_result_file);
  1768.       }
  1769.       else if (my_isalpha(charset_info, *ptr) ||
  1770.        (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
  1771.         fputs("NULL", md_result_file);
  1772.       else if (field->type == FIELD_TYPE_DECIMAL)
  1773.       {
  1774. /* add " signs around */
  1775. fputc(''', md_result_file);
  1776. fputs(ptr, md_result_file);
  1777. fputc(''', md_result_file);
  1778.       }
  1779.       else
  1780. fputs(ptr, md_result_file);
  1781.     }
  1782.   }
  1783.   else
  1784.           {
  1785.             /* The field value is NULL */
  1786.             if (!opt_xml)
  1787.               fputs("NULL", md_result_file);
  1788.             else
  1789.               print_xml_null_tag(md_result_file, "tt", "field name=",
  1790.                                  field->name, "n");
  1791.           }
  1792.           check_io(md_result_file);
  1793. }
  1794.       }
  1795.       if (opt_xml)
  1796.       {
  1797.         fputs("t</row>n", md_result_file);
  1798. check_io(md_result_file);
  1799.       }
  1800.       if (extended_insert)
  1801.       {
  1802. ulong row_length;
  1803. dynstr_append(&extended_row,")");
  1804.         row_length = 2 + extended_row.length;
  1805.         if (total_length + row_length < opt_net_buffer_length)
  1806.         {
  1807.   total_length += row_length;
  1808.   fputc(',',md_result_file); /* Always row break */
  1809.   fputs(extended_row.str,md_result_file);
  1810. }
  1811.         else
  1812.         {
  1813.   if (row_break)
  1814.     fputs(";n", md_result_file);
  1815.   row_break=1; /* This is first row */
  1816.           fputs(insert_pat.str,md_result_file);
  1817.           fputs(extended_row.str,md_result_file);
  1818.   total_length = row_length+init_length;
  1819.         }
  1820. check_io(md_result_file);
  1821.       }
  1822.       else if (!opt_xml)
  1823.       {
  1824. fputs(");n", md_result_file);
  1825. check_io(md_result_file);
  1826.       }
  1827.     }
  1828.     /* XML - close table tag and supress regular output */
  1829.     if (opt_xml)
  1830. fputs("t</table_data>n", md_result_file);
  1831.     else if (extended_insert && row_break)
  1832.       fputs(";n", md_result_file); /* If not empty table */
  1833.     fflush(md_result_file);
  1834.     check_io(md_result_file);
  1835.     if (mysql_errno(sock))
  1836.     {
  1837.       my_snprintf(query, QUERY_LENGTH,
  1838.   "%s: Error %d: %s when dumping table %s at row: %ldn",
  1839.   my_progname,
  1840.   mysql_errno(sock),
  1841.   mysql_error(sock),
  1842.   result_table,
  1843.   rownr);
  1844.       fputs(query,stderr);
  1845.       error= EX_CONSCHECK;
  1846.       goto err;
  1847.     }
  1848.     if (opt_lock)
  1849.     {
  1850.       fputs("UNLOCK TABLES;n", md_result_file);
  1851.       check_io(md_result_file);
  1852.     }
  1853.     if (opt_disable_keys)
  1854.     {
  1855.       fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;n",
  1856.       opt_quoted_table);
  1857.       check_io(md_result_file);
  1858.     }
  1859.     if (opt_autocommit)
  1860.     {
  1861.       fprintf(md_result_file, "commit;n");
  1862.       check_io(md_result_file);
  1863.     }
  1864.     mysql_free_result(res);
  1865.     if (query != query_buf)
  1866.       my_free(query, MYF(MY_ALLOW_ZERO_PTR));
  1867.   } 
  1868.   return;
  1869. err:
  1870.   if (query != query_buf)
  1871.     my_free(query, MYF(MY_ALLOW_ZERO_PTR));
  1872.   safe_exit(error);
  1873.   return;
  1874. } /* dumpTable */
  1875. static char *getTableName(int reset)
  1876. {
  1877.   static MYSQL_RES *res = NULL;
  1878.   MYSQL_ROW    row;
  1879.   if (!res)
  1880.   {
  1881.     if (!(res = mysql_list_tables(sock,NullS)))
  1882.       return(NULL);
  1883.   }
  1884.   if ((row = mysql_fetch_row(res)))
  1885.     return((char*) row[0]);
  1886.   if (reset)
  1887.     mysql_data_seek(res,0);      /* We want to read again */
  1888.   else
  1889.   {
  1890.     mysql_free_result(res);
  1891.     res = NULL;
  1892.   }
  1893.   return(NULL);
  1894. } /* getTableName */
  1895. static int dump_all_databases()
  1896. {
  1897.   MYSQL_ROW row;
  1898.   MYSQL_RES *tableres;
  1899.   int result=0;
  1900.   if (mysql_query_with_error_report(sock, &tableres, "SHOW DATABASES"))
  1901.     return 1;
  1902.   while ((row = mysql_fetch_row(tableres)))
  1903.   {
  1904.     if (dump_all_tables_in_db(row[0]))
  1905.       result=1;
  1906.   }
  1907.   return result;
  1908. }
  1909. /* dump_all_databases */
  1910. static int dump_databases(char **db_names)
  1911. {
  1912.   int result=0;
  1913.   for ( ; *db_names ; db_names++)
  1914.   {
  1915.     if (dump_all_tables_in_db(*db_names))
  1916.       result=1;
  1917.   }
  1918.   return result;
  1919. } /* dump_databases */
  1920. static int init_dumping(char *database)
  1921. {
  1922.   if (mysql_select_db(sock, database))
  1923.   {
  1924.     DBerror(sock, "when selecting the database");
  1925.     return 1; /* If --force */
  1926.   }
  1927.   if (!path && !opt_xml)
  1928.   {
  1929.     if (opt_databases || opt_alldbs)
  1930.     {
  1931.       /*
  1932. length of table name * 2 (if name contains quotes), 2 quotes and 0
  1933.       */
  1934.       char quoted_database_buf[64*2+3];
  1935.       char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
  1936.       if (opt_comments)
  1937.       {
  1938. fprintf(md_result_file,"n--n-- Current Database: %sn--n", qdatabase);
  1939. check_io(md_result_file);
  1940.       }
  1941.       if (!opt_create_db)
  1942.       {
  1943.         char qbuf[256];
  1944.         MYSQL_ROW row;
  1945.         MYSQL_RES *dbinfo;
  1946.         my_snprintf(qbuf, sizeof(qbuf), 
  1947.     "SHOW CREATE DATABASE IF NOT EXISTS %s",
  1948.     qdatabase);
  1949.         if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock)))
  1950.         {
  1951.           /* Old server version, dump generic CREATE DATABASE */
  1952.           if (opt_drop_database)
  1953.             fprintf(md_result_file,
  1954.                     "n/*!40000 DROP DATABASE IF EXISTS %s;*/n",
  1955.                     qdatabase);
  1956.   fprintf(md_result_file,
  1957.   "nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;n",
  1958.   qdatabase);
  1959. }
  1960. else
  1961.         {
  1962.           if (opt_drop_database)
  1963.             fprintf(md_result_file,
  1964.                     "n/*!40000 DROP DATABASE IF EXISTS %s*/;n",
  1965.                     qdatabase);
  1966.   row = mysql_fetch_row(dbinfo);
  1967.   if (row[1])
  1968.   {
  1969.     fprintf(md_result_file,"n%s;n",row[1]);
  1970.           }
  1971. }
  1972.       }
  1973.       fprintf(md_result_file,"nUSE %s;n", qdatabase);
  1974.       check_io(md_result_file);
  1975.     }
  1976.   }
  1977.   if (extended_insert && init_dynamic_string(&extended_row, "", 1024, 1024))
  1978.     exit(EX_EOM);
  1979.   return 0;
  1980. } /* init_dumping */
  1981. my_bool include_table(byte* hash_key, uint len)
  1982. {
  1983.   if (hash_search(&ignore_table, (byte*) hash_key, len))
  1984.     return FALSE;
  1985.   return TRUE;
  1986. }
  1987. static int dump_all_tables_in_db(char *database)
  1988. {
  1989.   char *table;
  1990.   uint numrows;
  1991.   char table_buff[NAME_LEN*2+3];
  1992.   char hash_key[2*NAME_LEN+2];  /* "db.tablename" */
  1993.   char *afterdot;
  1994.   afterdot= strmov(hash_key, database);
  1995.   *afterdot++= '.';
  1996.   if (init_dumping(database))
  1997.     return 1;
  1998.   if (opt_xml)
  1999.     print_xml_tag1(md_result_file, "", "database name=", database, "n");
  2000.   if (lock_tables)
  2001.   {
  2002.     DYNAMIC_STRING query;
  2003.     init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
  2004.     for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
  2005.     {
  2006.       dynstr_append(&query, quote_name(table, table_buff, 1));
  2007.       dynstr_append(&query, " READ /*!32311 LOCAL */,");
  2008.     }
  2009.     if (numrows && mysql_real_query(sock, query.str, query.length-1))
  2010.       DBerror(sock, "when using LOCK TABLES");
  2011.             /* We shall continue here, if --force was given */
  2012.     dynstr_free(&query);
  2013.   }
  2014.   if (flush_logs)
  2015.   {
  2016.     if (mysql_refresh(sock, REFRESH_LOG))
  2017.       DBerror(sock, "when doing refresh");
  2018.            /* We shall continue here, if --force was given */
  2019.   }
  2020.   while ((table= getTableName(0)))
  2021.   {
  2022.     char *end= strmov(afterdot, table);
  2023.     if (include_table(hash_key, end - hash_key))
  2024.     {
  2025.       numrows = getTableStructure(table, database);
  2026.       if (!dFlag && numrows > 0)
  2027. dumpTable(numrows,table);
  2028.       my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
  2029.       order_by= 0;
  2030.     }
  2031.   }
  2032.   if (opt_xml)
  2033.   {
  2034.     fputs("</database>n", md_result_file);
  2035.     check_io(md_result_file);
  2036.   }
  2037.   if (lock_tables)
  2038.     mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
  2039.   return 0;
  2040. } /* dump_all_tables_in_db */
  2041. /*
  2042.   get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual 
  2043.   table name from the server for the table name given on the command line.  
  2044.   we do this because the table name given on the command line may be a 
  2045.   different case (e.g.  T1 vs t1)
  2046.   
  2047.   RETURN
  2048.     int - 0 if a tablename was retrieved.  1 if not
  2049. */
  2050. static int get_actual_table_name(const char *old_table_name, 
  2051.                                   char *new_table_name, 
  2052.                                   int buf_size)
  2053. {
  2054.   int retval;
  2055.   MYSQL_RES  *tableRes;
  2056.   MYSQL_ROW  row;
  2057.   char query[50 + 2*NAME_LEN];
  2058.   char show_name_buff[FN_REFLEN];
  2059.   DBUG_ENTER("get_actual_table_name");
  2060.   DBUG_PRINT("enter", ("old_table_name: %s", old_table_name));
  2061.   /* Check memory for quote_for_like() */
  2062.   DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
  2063.   my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", 
  2064.       quote_for_like(old_table_name, show_name_buff));
  2065.   if (mysql_query_with_error_report(sock, 0, query))
  2066.   {
  2067.     safe_exit(EX_MYSQLERR);
  2068.   }
  2069.   tableRes= mysql_store_result( sock );
  2070.   retval = 1;
  2071.   if (tableRes != NULL)
  2072.   {
  2073.     my_ulonglong numRows= mysql_num_rows(tableRes);
  2074.     if (numRows > 0)
  2075.     {
  2076.       row= mysql_fetch_row( tableRes );
  2077.       strmake(new_table_name, row[0], buf_size-1);
  2078.       retval= 0;
  2079.       DBUG_PRINT("info", ("new_table_name: %s", new_table_name));
  2080.     }
  2081.     mysql_free_result(tableRes);
  2082.   }
  2083.   DBUG_PRINT("exit", ("retval: %d", retval));
  2084.   DBUG_RETURN(retval);
  2085. }
  2086. static int dump_selected_tables(char *db, char **table_names, int tables)
  2087. {
  2088.   uint numrows, i;
  2089.   char table_buff[NAME_LEN*+3];
  2090.   char new_table_name[NAME_LEN];
  2091.   DYNAMIC_STRING lock_tables_query;
  2092.   HASH dump_tables;
  2093.   DBUG_ENTER("dump_selected_tables");
  2094.   if (init_dumping(db))
  2095.     return 1;
  2096.   /* Init hash table for storing the actual name of tables to dump */
  2097.   if (hash_init(&dump_tables, charset_info, 16, 0, 0,
  2098.                 (hash_get_key) get_table_key, (hash_free_key) free_table_ent,
  2099.                 0))
  2100.     exit(EX_EOM);
  2101.   init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024);
  2102.   for (; tables > 0 ; tables-- , table_names++)
  2103.   {
  2104.     /* the table name passed on commandline may be wrong case */
  2105.     if (!get_actual_table_name(*table_names,
  2106.                                new_table_name, sizeof(new_table_name) ))
  2107.     {
  2108.       /* Add found table name to lock_tables_query */
  2109.       if (lock_tables)
  2110.       {
  2111.         dynstr_append(&lock_tables_query,
  2112.                       quote_name(new_table_name, table_buff, 1));
  2113.         dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,");
  2114.       }
  2115.       /* Add found table name to dump_tables list */
  2116.       if (my_hash_insert(&dump_tables,
  2117.                          (byte*)my_strdup(new_table_name, MYF(0))))
  2118.         exit(EX_EOM);
  2119.     }
  2120.     else
  2121.     {
  2122.        my_printf_error(0,"Couldn't find table: "%s"n", MYF(0),
  2123.                        *table_names);
  2124.        safe_exit(EX_ILLEGAL_TABLE);
  2125.        /* We shall countinue here, if --force was given */
  2126.     }
  2127.   }
  2128.   if (lock_tables)
  2129.   {
  2130.     if (mysql_real_query(sock, lock_tables_query.str,
  2131.                          lock_tables_query.length-1))
  2132.       DBerror(sock, "when doing LOCK TABLES");
  2133.        /* We shall countinue here, if --force was given */
  2134.   }
  2135.   dynstr_free(&lock_tables_query);
  2136.   if (flush_logs)
  2137.   {
  2138.     if (mysql_refresh(sock, REFRESH_LOG))
  2139.       DBerror(sock, "when doing refresh");
  2140.      /* We shall countinue here, if --force was given */
  2141.   }
  2142.   if (opt_xml)
  2143.     print_xml_tag1(md_result_file, "", "database name=", db, "n");
  2144.   /* Dump each selected table */
  2145.   for (i= 0 ; i < dump_tables.records ; i++)
  2146.   {
  2147.     const char *table_name= hash_element(&dump_tables, i);
  2148.     DBUG_PRINT("info",("Dumping table %s", table_name));
  2149.     numrows= getTableStructure((char*) table_name, db);
  2150.     if (!dFlag && numrows > 0)
  2151.       dumpTable(numrows, (char*) table_name);
  2152.   }
  2153.   hash_free(&dump_tables);
  2154.   my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
  2155.   order_by= 0;
  2156.   if (opt_xml)
  2157.   {
  2158.     fputs("</database>n", md_result_file);
  2159.     check_io(md_result_file);
  2160.   }
  2161.   if (lock_tables)
  2162.     mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
  2163.   DBUG_RETURN(0);
  2164. } /* dump_selected_tables */
  2165. static int do_show_master_status(MYSQL *mysql_con)
  2166. {
  2167.   MYSQL_ROW row;
  2168.   MYSQL_RES *master;
  2169.   const char *comment_prefix=
  2170.     (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
  2171.   if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
  2172.   {
  2173.     my_printf_error(0, "Error: Couldn't execute 'SHOW MASTER STATUS': %s",
  2174.                     MYF(0), mysql_error(mysql_con));
  2175.     return 1;
  2176.   }
  2177.   else
  2178.   {
  2179.     row = mysql_fetch_row(master);
  2180.     if (row && row[0] && row[1])
  2181.     {
  2182.       /* SHOW MASTER STATUS reports file and position */
  2183.       if (opt_comments)
  2184.         fprintf(md_result_file,
  2185.                 "n--n-- Position to start replication or point-in-time "
  2186.                 "recovery fromn--nn");
  2187.       fprintf(md_result_file,
  2188.               "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;n",
  2189.               comment_prefix, row[0], row[1]); 
  2190.       check_io(md_result_file);
  2191.     }
  2192.     else if (!ignore_errors)
  2193.     {
  2194.       /* SHOW MASTER STATUS reports nothing and --force is not enabled */
  2195.       my_printf_error(0, "Error: Binlogging on server not active", 
  2196.       MYF(0));
  2197.       mysql_free_result(master);
  2198.       return 1;
  2199.     }
  2200.     mysql_free_result(master);
  2201.   }
  2202.   return 0;
  2203. }
  2204. static int do_flush_tables_read_lock(MYSQL *mysql_con)
  2205. {
  2206.   /*
  2207.     We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
  2208.     will wait but will not stall the whole mysqld, and when the long update is
  2209.     done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
  2210.     FLUSH TABLES is to lower the probability of a stage where both mysqldump
  2211.     and most client connections are stalled. Of course, if a second long
  2212.     update starts between the two FLUSHes, we have that bad stall.
  2213.   */
  2214.   return 
  2215.     ( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") ||
  2216.       mysql_query_with_error_report(mysql_con, 0,
  2217.                                     "FLUSH TABLES WITH READ LOCK") );
  2218. }
  2219. static int do_unlock_tables(MYSQL *mysql_con)
  2220. {
  2221.   return mysql_query_with_error_report(mysql_con, 0, "UNLOCK TABLES");
  2222. }
  2223. static int do_reset_master(MYSQL *mysql_con)
  2224. {
  2225.   return mysql_query_with_error_report(mysql_con, 0, "RESET MASTER");
  2226. }
  2227. static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now)
  2228. {
  2229.   /*
  2230.     We use BEGIN for old servers. --single-transaction --master-data will fail
  2231.     on old servers, but that's ok as it was already silently broken (it didn't
  2232.     do a consistent read, so better tell people frankly, with the error).
  2233.     We want the first consistent read to be used for all tables to dump so we
  2234.     need the REPEATABLE READ level (not anything lower, for example READ
  2235.     COMMITTED would give one new consistent read per dumped table).
  2236.   */
  2237.   return (mysql_query_with_error_report(mysql_con, 0,
  2238.                                         "SET SESSION TRANSACTION ISOLATION "
  2239.                                         "LEVEL REPEATABLE READ") ||
  2240.           mysql_query_with_error_report(mysql_con, 0,
  2241.                                         consistent_read_now ?
  2242.                                         "START TRANSACTION "
  2243.                                         "WITH CONSISTENT SNAPSHOT" :
  2244.                                         "BEGIN"));
  2245. }
  2246. static ulong find_set(TYPELIB *lib, const char *x, uint length,
  2247.       char **err_pos, uint *err_len)
  2248. {
  2249.   const char *end= x + length;
  2250.   ulong found= 0;
  2251.   uint find;
  2252.   char buff[255];
  2253.   *err_pos= 0;                  /* No error yet */
  2254.   while (end > x && my_isspace(charset_info, end[-1]))
  2255.     end--;
  2256.   *err_len= 0;
  2257.   if (x != end)
  2258.   {
  2259.     const char *start= x;
  2260.     for (;;)
  2261.     {
  2262.       const char *pos= start;
  2263.       uint var_len;
  2264.       for (; pos != end && *pos != ','; pos++) ;
  2265.       var_len= (uint) (pos - start);
  2266.       strmake(buff, start, min(sizeof(buff), var_len));
  2267.       find= find_type(buff, lib, var_len);
  2268.       if (!find)
  2269.       {
  2270.         *err_pos= (char*) start;
  2271.         *err_len= var_len;
  2272.       }
  2273.       else
  2274.         found|= ((longlong) 1 << (find - 1));
  2275.       if (pos == end)
  2276.         break;
  2277.       start= pos + 1;
  2278.     }
  2279.   }
  2280.   return found;
  2281. }
  2282. /* Print a value with a prefix on file */
  2283. static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
  2284. const char *prefix, const char *name,
  2285. int string_value)
  2286. {
  2287.   MYSQL_FIELD *field;
  2288.   mysql_field_seek(result, 0);
  2289.   for ( ; (field = mysql_fetch_field(result)) ; row++)
  2290.   {
  2291.     if (!strcmp(field->name,name))
  2292.     {
  2293.       if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
  2294.       {
  2295. fputc(' ',file);
  2296. fputs(prefix, file);
  2297. if (string_value)
  2298.   unescape(file,row[0],(uint) strlen(row[0]));
  2299. else
  2300.   fputs(row[0], file);
  2301. check_io(file);
  2302. return;
  2303.       }
  2304.     }
  2305.   }
  2306.   return; /* This shouldn't happen */
  2307. } /* print_value */
  2308. /*
  2309.   Check if we the table is one of the table types that should be ignored:
  2310.   MRG_ISAM, MRG_MYISAM
  2311.   SYNOPSIS
  2312.     check_if_ignore_table()
  2313.     table_name Table name to check
  2314.   GLOBAL VARIABLES
  2315.     sock MySQL socket
  2316.     verbose Write warning messages
  2317.   RETURN
  2318.     0 Table should be backuped
  2319.     # Type of table (that should be skipped)
  2320. */
  2321. static const char *check_if_ignore_table(const char *table_name)
  2322. {
  2323.   char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
  2324.   MYSQL_RES *res;
  2325.   MYSQL_ROW row;
  2326.   const char *result= 0;
  2327.   /* Check memory for quote_for_like() */
  2328.   DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff));
  2329.   my_snprintf(buff, sizeof(buff), "show table status like %s",
  2330.       quote_for_like(table_name, show_name_buff));
  2331.   if (mysql_query_with_error_report(sock, &res, buff))
  2332.   {
  2333.     if (mysql_errno(sock) != ER_PARSE_ERROR)
  2334.     { /* If old MySQL version */
  2335.       if (verbose)
  2336. fprintf(stderr,
  2337. "-- Warning: Couldn't get status information for table %s (%s)n",
  2338. table_name,mysql_error(sock));
  2339.       return 0; /* assume table is ok */
  2340.     }
  2341.   }
  2342.   if (!(row= mysql_fetch_row(res)))
  2343.   {
  2344.     fprintf(stderr,
  2345.     "Error: Couldn't read status information for table %s (%s)n",
  2346.     table_name, mysql_error(sock));
  2347.     mysql_free_result(res);
  2348.     return 0; /* assume table is ok */
  2349.   }
  2350.   if (strcmp(row[1], (result= "MRG_MyISAM")) &&
  2351.       strcmp(row[1], (result= "MRG_ISAM")))
  2352.     result= 0;
  2353.   mysql_free_result(res);
  2354.   return result;
  2355. }
  2356. /*
  2357.   Get string of comma-separated primary key field names
  2358.   SYNOPSIS
  2359.     char *primary_key_fields(const char *table_name)
  2360.     RETURNS     pointer to allocated buffer (must be freed by caller)
  2361.     table_name  quoted table name
  2362.   DESCRIPTION
  2363.     Use SHOW KEYS FROM table_name, allocate a buffer to hold the
  2364.     field names, and then build that string and return the pointer
  2365.     to that buffer.
  2366.     Returns NULL if there is no PRIMARY or UNIQUE key on the table,
  2367.     or if there is some failure.  It is better to continue to dump
  2368.     the table unsorted, rather than exit without dumping the data.
  2369. */
  2370. static char *primary_key_fields(const char *table_name)
  2371. {
  2372.   MYSQL_RES  *res = NULL;
  2373.   MYSQL_ROW  row;
  2374.   /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes +  */
  2375.   char show_keys_buff[15 + 64 * 2 + 3];
  2376.   uint result_length = 0;
  2377.   char *result = 0;
  2378.   my_snprintf(show_keys_buff, sizeof(show_keys_buff), 
  2379.       "SHOW KEYS FROM %s", table_name);
  2380.   if (mysql_query(sock, show_keys_buff) ||
  2381.       !(res = mysql_store_result(sock)))
  2382.   {
  2383.     fprintf(stderr, "Warning: Couldn't read keys from table %s;"
  2384.             " records are NOT sorted (%s)n",
  2385.             table_name, mysql_error(sock));
  2386.     /* Don't exit, because it's better to print out unsorted records */
  2387.     goto cleanup;
  2388.   }
  2389.   /*
  2390.    * Figure out the length of the ORDER BY clause result.
  2391.    * Note that SHOW KEYS is ordered:  a PRIMARY key is always the first
  2392.    * row, and UNIQUE keys come before others.  So we only need to check
  2393.    * the first key, not all keys.
  2394.    */
  2395.   if ((row = mysql_fetch_row(res)) && atoi(row[1]) == 0)
  2396.   {
  2397.     /* Key is unique */
  2398.     do
  2399.       result_length += strlen(row[4]) + 1;      /* + 1 for ',' or  */
  2400.     while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1);
  2401.   }
  2402.   /* Build the ORDER BY clause result */
  2403.   if (result_length) {
  2404.     char *end;
  2405.     /* result (terminating  is already in result_length) */
  2406.     result = my_malloc(result_length + 10, MYF(MY_WME));
  2407.     if (!result) {
  2408.       fprintf(stderr, "Error: Not enough memory to store ORDER BY clausen");
  2409.       goto cleanup;
  2410.     }
  2411.     mysql_data_seek(res, 0);
  2412.     row = mysql_fetch_row(res);
  2413.     end = strmov(result, row[4]);
  2414.     while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1)
  2415.       end = strxmov(end, ",", row[4], NullS);
  2416.   }
  2417. cleanup:
  2418.   if (res)
  2419.     mysql_free_result(res);
  2420.   return result;
  2421. }
  2422. int main(int argc, char **argv)
  2423. {
  2424.   compatible_mode_normal_str[0]= 0;
  2425.   default_charset= (char *)mysql_universal_client_charset;
  2426.   bzero((char*) &ignore_table, sizeof(ignore_table));
  2427.   MY_INIT("mysqldump");
  2428.   if (get_options(&argc, &argv))
  2429.   {
  2430.     my_end(0);
  2431.     exit(EX_USAGE);
  2432.   }
  2433.   if (dbConnect(current_host, current_user, opt_password))
  2434.     exit(EX_MYSQLERR);
  2435.   if (!path)
  2436.     write_header(md_result_file, *argv);
  2437.   if ((opt_lock_all_tables || opt_master_data) &&
  2438.       do_flush_tables_read_lock(sock))
  2439.     goto err;
  2440.   if (opt_single_transaction && start_transaction(sock, test(opt_master_data)))
  2441.       goto err;
  2442.   if (opt_delete_master_logs && do_reset_master(sock))
  2443.     goto err;
  2444.   if (opt_lock_all_tables || opt_master_data)
  2445.   {
  2446.     if (flush_logs && mysql_refresh(sock, REFRESH_LOG))
  2447.       goto err;
  2448.     flush_logs= 0; /* not anymore; that would not be sensible */
  2449.   }
  2450.   if (opt_master_data && do_show_master_status(sock))
  2451.     goto err;
  2452.   if (opt_single_transaction && do_unlock_tables(sock)) /* unlock but no commit! */
  2453.     goto err;
  2454.   if (opt_alldbs)
  2455.     dump_all_databases();
  2456.   else if (argc > 1 && !opt_databases)
  2457.   {
  2458.     /* Only one database and selected table(s) */
  2459.     dump_selected_tables(*argv, (argv + 1), (argc - 1));
  2460.   }
  2461.   else
  2462.   {
  2463.     /* One or more databases, all tables */
  2464.     dump_databases(argv);
  2465.   }
  2466. #ifdef HAVE_SMEM
  2467.   my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
  2468. #endif
  2469.   /*
  2470.     No reason to explicitely COMMIT the transaction, neither to explicitely
  2471.     UNLOCK TABLES: these will be automatically be done by the server when we
  2472.     disconnect now. Saves some code here, some network trips, adds nothing to
  2473.     server.
  2474.   */
  2475. err:
  2476.   dbDisconnect(current_host);
  2477.   if (!path)
  2478.     write_footer(md_result_file);
  2479.   if (md_result_file != stdout)
  2480.     my_fclose(md_result_file, MYF(0));
  2481.   my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
  2482.   if (hash_inited(&ignore_table))
  2483.     hash_free(&ignore_table);
  2484.   if (extended_insert)
  2485.     dynstr_free(&extended_row);
  2486.   if (insert_pat_inited)
  2487.     dynstr_free(&insert_pat);
  2488.   my_end(0);
  2489.   return(first_error);
  2490. } /* main */