home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / client / mysqldump.c < prev    next >
C/C++ Source or Header  |  2000-11-16  |  39KB  |  1,369 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.  
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.  
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16.  
  17. /* mysqldump.c  - Dump a tables contents and format to an ASCII file
  18. **
  19. ** The author's original notes follow :-
  20. **
  21. **        ******************************************************
  22. **        *                             *
  23. **        * AUTHOR: Igor Romanenko (igor@frog.kiev.ua)         *
  24. **        * DATE:   December 3, 1994                 *
  25. **        * WARRANTY: None, expressed, impressed, implied      *
  26. **        *        or other                     *
  27. **        * STATUS: Public domain                     *
  28. **        * Adapted and optimized for MySQL by             *
  29. **        * Michael Widenius, Sinisa Milivojevic, Jani Tolonen *
  30. **        * -w --where added 9/10/98 by Jim Faucette         *
  31. **        * slave code by David Saez Padros <david@ols.es>     *
  32. **        *                             *
  33. **        ******************************************************
  34. */
  35. /* SSL by
  36. **   Andrei Errapart <andreie@no.spam.ee>
  37. **   T⌡nu Samuel  <tonu@please.do.not.remove.this.spam.ee>
  38. **/
  39.  
  40. #define DUMP_VERSION "8.11"
  41.  
  42. #include <global.h>
  43. #include <my_sys.h>
  44. #include <m_string.h>
  45. #include <m_ctype.h>
  46.  
  47. #include "mysql.h"
  48. #include "mysql_version.h"
  49. #include "mysqld_error.h"
  50. #include <getopt.h>
  51.  
  52. /* Exit codes */
  53.  
  54. #define EX_USAGE 1
  55. #define EX_MYSQLERR 2
  56. #define EX_CONSCHECK 3
  57. #define EX_EOM 4
  58.  
  59. /* index into 'show fields from table' */
  60.  
  61. #define SHOW_FIELDNAME  0
  62. #define SHOW_TYPE  1
  63. #define SHOW_NULL  2
  64. #define SHOW_DEFAULT  4
  65. #define SHOW_EXTRA  5
  66. #define QUOTE_CHAR    '`'
  67.  
  68. static char *add_load_option(char *ptr, const char *object,
  69.                  const char *statement);
  70.  
  71. static char *field_escape(char *to,const char *from,uint length);
  72. static my_bool  verbose=0,tFlag=0,cFlag=0,dFlag=0,quick=0, extended_insert = 0,
  73.         lock_tables=0,ignore_errors=0,flush_logs=0,replace=0,
  74.         ignore=0,opt_drop=0,opt_keywords=0,opt_lock=0,opt_compress=0,
  75.                 opt_delayed=0,create_options=0,opt_quoted=0,opt_databases=0,
  76.                 opt_alldbs=0,opt_create_db=0,opt_first_slave=0;
  77. static MYSQL  mysql_connection,*sock=0;
  78. static char  insert_pat[12 * 1024],*opt_password=0,*current_user=0,
  79.              *current_host=0,*path=0,*fields_terminated=0,
  80.              *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
  81.              *where=0, *default_charset;
  82. static uint     opt_mysql_port=0;
  83. static my_string opt_mysql_unix_port=0;
  84. static int   first_error=0;
  85. extern ulong net_buffer_length;
  86. static DYNAMIC_STRING extended_row;
  87. #include "sslopt-vars.h"
  88.  
  89. enum options {OPT_FTB=256, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_KEYWORDS,
  90.           OPT_LOCKS, OPT_DROP, OPT_OPTIMIZE, OPT_DELAYED, OPT_TABLES,
  91.               OPT_CHARSETS_DIR, OPT_DEFAULT_CHARSET};
  92.  
  93. static struct option long_options[] =
  94. {
  95.   {"all-databases",     no_argument,    0,      'A'},
  96.   {"all",        no_argument,    0,     'a'},
  97.   {"add-drop-table",    no_argument,    0,     OPT_DROP},
  98.   {"add-locks",        no_argument,    0,    OPT_LOCKS},
  99.   {"allow-keywords",    no_argument,    0,     OPT_KEYWORDS},
  100.   {"character-sets-dir",required_argument,0,    OPT_CHARSETS_DIR},
  101.   {"complete-insert",    no_argument,    0,     'c'},
  102.   {"compress",          no_argument,    0,     'C'},
  103.   {"databases",         no_argument,    0,      'B'},
  104.   {"debug",        optional_argument,     0, '#'},
  105.   {"default-character-set", required_argument,  0, OPT_DEFAULT_CHARSET},
  106.   {"delayed-insert",    no_argument,    0,     OPT_DELAYED},
  107.   {"extended-insert",   no_argument,    0,     'e'},
  108.   {"fields-terminated-by", required_argument,   0, (int) OPT_FTB},
  109.   {"fields-enclosed-by", required_argument,    0, (int) OPT_ENC},
  110.   {"fields-optionally-enclosed-by", required_argument, 0, (int) OPT_O_ENC},
  111.   {"fields-escaped-by", required_argument,    0, (int) OPT_ESC},
  112.   {"first-slave",    no_argument,    0,    'x'},
  113.   {"flush-logs",    no_argument,    0,    'F'},
  114.   {"force",            no_argument,    0,    'f'},
  115.   {"help",           no_argument,    0,    '?'},
  116.   {"host",            required_argument,    0, 'h'},
  117.   {"lines-terminated-by", required_argument,    0, (int) OPT_LTB},
  118.   {"lock-tables",      no_argument,    0,     'l'},
  119.   {"no-create-db",      no_argument,    0,      'n'},
  120.   {"no-create-info",     no_argument,    0,     't'},
  121.   {"no-data",          no_argument,    0,     'd'},
  122.   {"opt",           no_argument,    0,     OPT_OPTIMIZE},
  123.   {"password",      optional_argument,     0, 'p'},
  124. #ifdef __WIN__
  125.   {"pipe",        no_argument,           0, 'W'},
  126. #endif
  127.   {"port",            required_argument,    0, 'P'},
  128.   {"quick",            no_argument,        0, 'q'},
  129.   {"quote-names",    no_argument,        0, 'Q'},
  130.   {"set-variable",    required_argument,    0, 'O'},
  131.   {"socket",           required_argument,    0, 'S'},
  132. #include "sslopt-longopts.h"
  133.   {"tab",            required_argument,    0, 'T'},
  134.   {"tables",            no_argument,            0, OPT_TABLES},
  135. #ifndef DONT_ALLOW_USER_CHANGE
  136.   {"user",            required_argument,    0, 'u'},
  137. #endif
  138.   {"verbose",        no_argument,        0, 'v'},
  139.   {"version",        no_argument,        0, 'V'},
  140.   {"where",        required_argument,     0, 'w'},
  141.   {0, 0, 0, 0}
  142. };
  143.  
  144. static const char *load_default_groups[]= { "mysqldump","client",0 };
  145.  
  146. CHANGEABLE_VAR changeable_vars[] = {
  147.   { "max_allowed_packet", (long*) &max_allowed_packet,24*1024*1024,4096,
  148.     24*1024L*1024L,MALLOC_OVERHEAD,1024},
  149.   { "net_buffer_length", (long*) &net_buffer_length,1024*1024L-1025,4096,
  150.     24*1024L*1024L,MALLOC_OVERHEAD,1024},
  151.   { 0, 0, 0, 0, 0, 0, 0}
  152. };
  153.  
  154. static void safe_exit(int error);
  155. static void write_heder(FILE *sql_file, char *db_name);
  156. static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
  157.             const char *prefix,const char *name,
  158.             int string_value);
  159. static int dump_selected_tables(char *db, char **table_names, int tables);
  160. static int dump_all_tables_in_db(char *db);
  161. static int init_dumping(char *);
  162. static int dump_databases(char **);
  163. static int dump_all_databases();
  164. static char *quote_name(char *name, char *buff);
  165.  
  166. static void print_version(void)
  167. {
  168.   printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
  169.    MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
  170. } /* print_version */
  171.  
  172.  
  173. static void usage(void)
  174. {
  175.   uint i;
  176.   print_version();
  177.   puts("By Igor Romanenko, Monty, Jani & Sinisa");
  178.   puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
  179.   puts("Dumping definition and data mysql database or table");
  180.   printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
  181.   printf("OR     %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
  182.      my_progname);
  183.   printf("OR     %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
  184.   printf("\n\
  185.   -A, --all-databases   Dump all the databases. This will be same as\n\
  186.                 --databases with all databases selected.\n\
  187.   -a, --all        Include all MySQL specific create options.\n\
  188.   -#, --debug=...       Output debug log. Often this is 'd:t:o,filename`.\n\
  189.   --character-sets-dir=...\n\
  190.                         Directory where character sets are\n\
  191.   -?, --help        Display this help message and exit.\n\
  192.   -B, --databases       To dump several databases. Note the difference in\n\
  193.             usage; In this case no tables are given. All name\n\
  194.             arguments are regarded as databasenames.\n\
  195.             'USE db_name;' will be included in the output\n\
  196.   -c, --complete-insert Use complete insert statements.\n\
  197.   -C, --compress        Use compression in server/client protocol.\n\
  198.   --default-character-set=...\n\
  199.                         Set the default character set\n\
  200.   -e, --extended-insert Allows utilization of the new, much faster\n\
  201.                         INSERT syntax.\n\
  202.   --add-drop-table    Add a 'drop table' before each create.\n\
  203.   --add-locks        Add locks around insert statements.\n\
  204.   --allow-keywords    Allow creation of column names that are keywords.\n\
  205.   --delayed-insert      Insert rows with INSERT DELAYED.\n\
  206.   -F, --flush-logs    Flush logs file in server before starting dump.\n\
  207.   -f, --force        Continue even if we get an sql-error.\n\
  208.   -h, --host=...    Connect to host.\n");
  209. puts("\
  210.   -l, --lock-tables     Lock all tables for read.\n\
  211.   -n, --no-create-db    'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;'\n\
  212.                         will not be put in the output. The above line will\n\
  213.                         be added otherwise, if --databases or\n\
  214.                         --all-databases option was given.\n\
  215.   -t, --no-create-info    Don't write table creation info.\n\
  216.   -d, --no-data        No row information.\n\
  217.   -O, --set-variable var=option\n\
  218.                         give a variable a value. --help lists variables\n\
  219.   --opt            Same as --add-drop-table --add-locks --all\n\
  220.                         --extended-insert --quick --lock-tables\n\
  221.   -p, --password[=...]    Password to use when connecting to server.\n\
  222.                         If password is not given it's solicited on the tty.\n");
  223. #ifdef __WIN__
  224.   puts("-W, --pipe        Use named pipes to connect to server");
  225. #endif
  226.   printf("\
  227.   -P, --port=...    Port number to use for connection.\n\
  228.   -q, --quick        Don't buffer query, dump directly to stdout.\n\
  229.   -Q, --quote-names    Quote table and column names with `\n\
  230.   -S, --socket=...    Socket file to use for connection.\n\
  231.   --tables              Overrides option --databases (-B).\n");
  232. #include "sslopt-usage.h"
  233.   printf("\
  234.   -T, --tab=...         Creates tab separated textfile for each table to\n\
  235.                         given path. (creates .sql and .txt files).\n\
  236.                         NOTE: This only works if mysqldump is run on\n\
  237.                               the same machine as the mysqld daemon.\n");
  238. #ifndef DONT_ALLOW_USER_CHANGE
  239.   printf("\
  240.   -u, --user=#        User for login if not current user.\n");
  241. #endif
  242.   printf("\
  243.   -v, --verbose        Print info about the various stages.\n\
  244.   -V, --version        Output version information and exit.\n\
  245.   -w, --where=        dump only selected records; QUOTES mandatory!\n\
  246.   EXAMPLES: \"--where=user=\'jimf\'\" \"-wuserid>1\" \"-wuserid<1\"\n\
  247.   Use -T (--tab=...) with --fields-...\n\
  248.   --fields-terminated-by=...\n\
  249.                         Fields in the textfile are terminated by ...\n\
  250.   --fields-enclosed-by=...\n\
  251.                         Fields in the importfile are enclosed by ...\n\
  252.   --fields-optionally-enclosed-by=...\n\
  253.                         Fields in the i.file are opt. enclosed by ...\n\
  254.   --fields-escaped-by=...\n\
  255.                         Fields in the i.file are escaped by ...\n\
  256.   --lines-terminated-by=...\n\
  257.                         Lines in the i.file are terminated by ...\n\
  258. ");
  259.   print_defaults("my",load_default_groups);
  260.  
  261.   printf("\nPossible variables for option --set-variable (-O) are:\n");
  262.   for (i=0 ; changeable_vars[i].name ; i++)
  263.     printf("%-20s  current value: %lu\n",
  264.      changeable_vars[i].name,
  265.      (ulong) *changeable_vars[i].varptr);
  266. } /* usage */
  267.  
  268.  
  269. static void write_heder(FILE *sql_file, char *db_name)
  270. {
  271.   fprintf(sql_file, "# MySQL dump %s\n#\n", DUMP_VERSION);
  272.   fprintf(sql_file, "# Host: %s    Database: %s\n",
  273.       current_host ? current_host : "localhost", db_name ? db_name : "");
  274.   fputs("#--------------------------------------------------------\n",
  275.   sql_file);
  276.   fprintf(sql_file, "# Server version\t%s\n",
  277.       mysql_get_server_info(&mysql_connection));
  278.   return;
  279. } /* write_heder */
  280.  
  281.  
  282. static int get_options(int *argc,char ***argv)
  283. {
  284.   int c,option_index;
  285.   my_bool tty_password=0;
  286.  
  287.   load_defaults("my",load_default_groups,argc,argv);
  288.   set_all_changeable_vars(changeable_vars);
  289.   while ((c=getopt_long(*argc,*argv,"#::p::h:u:O:P:S:T:EBaAcCdefFlnqtvVw:?Ix",
  290.             long_options, &option_index)) != EOF)
  291.   {
  292.     switch(c) {
  293.     case 'a':
  294.       create_options=1;
  295.       break;
  296.     case 'e':
  297.       extended_insert=1;
  298.       break;
  299.     case 'A':
  300.       opt_alldbs=1;
  301.       break;
  302.     case OPT_DEFAULT_CHARSET:
  303.       default_charset= optarg;
  304.       break;
  305.     case OPT_CHARSETS_DIR:
  306.       charsets_dir= optarg;
  307.       break;
  308.     case 'f':
  309.       ignore_errors=1;
  310.       break;
  311.     case 'F':
  312.       flush_logs=1;
  313.       break;
  314.     case 'h':
  315.       my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
  316.       current_host=my_strdup(optarg,MYF(MY_WME));
  317.       break;
  318.     case 'n':
  319.       opt_create_db = 1;
  320.       break;
  321. #ifndef DONT_ALLOW_USER_CHANGE
  322.     case 'u':
  323.       current_user=optarg;
  324.       break;
  325. #endif
  326.     case 'O':
  327.       if (set_changeable_var(optarg, changeable_vars))
  328.       {
  329.     usage();
  330.     return(1);
  331.       }
  332.       break;
  333.     case 'p':
  334.       if (optarg)
  335.       {
  336.     char *start=optarg;
  337.     my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
  338.     opt_password=my_strdup(optarg,MYF(MY_FAE));
  339.     while (*optarg) *optarg++= 'x';        /* Destroy argument */
  340.     if (*start)
  341.       start[1]=0;                /* Cut length of argument */
  342.       }
  343.       else
  344.     tty_password=1;
  345.       break;
  346.     case 'P':
  347.       opt_mysql_port= (unsigned int) atoi(optarg);
  348.       break;
  349.     case 'S':
  350.       opt_mysql_unix_port= optarg;
  351.       break;
  352.     case 'W':
  353. #ifdef __WIN__
  354.       opt_mysql_unix_port=MYSQL_NAMEDPIPE;
  355. #endif
  356.       break;
  357.     case 'T':
  358.       path= optarg;
  359.       break;
  360.     case 'B':
  361.       opt_databases = 1;
  362.       break;
  363.     case '#':
  364.       DBUG_PUSH(optarg ? optarg : "d:t:o");
  365.       break;
  366.     case 'c': cFlag=1; break;
  367.     case 'C':
  368.       opt_compress=1;
  369.       break;
  370.     case 'd': dFlag=1; break;
  371.     case 'l': lock_tables=1; break;
  372.     case 'q': quick=1; break;
  373.     case 'Q': opt_quoted=1; break;
  374.     case 't': tFlag=1;  break;
  375.     case 'v': verbose=1; break;
  376.     case 'V': print_version(); exit(0);
  377.     case 'w':
  378.       where=optarg;
  379.       break;
  380.     case 'x':
  381.       opt_first_slave=1;
  382.       break;
  383.     default:
  384.       fprintf(stderr,"%s: Illegal option character '%c'\n",my_progname,opterr);
  385.       /* Fall throught */
  386.     case 'I':
  387.     case '?':
  388.       usage();
  389.       exit(0);
  390.     case (int) OPT_FTB:
  391.       fields_terminated= optarg;
  392.       break;
  393.     case (int) OPT_LTB:
  394.       lines_terminated= optarg;
  395.       break;
  396.     case (int) OPT_ENC:
  397.       enclosed= optarg;
  398.       break;
  399.     case (int) OPT_O_ENC:
  400.       opt_enclosed= optarg;
  401.       break;
  402.     case (int) OPT_ESC:
  403.       escaped= optarg;
  404.       break;
  405.     case (int) OPT_DROP:
  406.       opt_drop=1;
  407.       break;
  408.     case (int) OPT_KEYWORDS:
  409.       opt_keywords=1;
  410.       break;
  411.     case (int) OPT_LOCKS:
  412.       opt_lock=1;
  413.       break;
  414.     case (int) OPT_OPTIMIZE:
  415.       extended_insert=opt_drop=opt_lock=lock_tables=quick=create_options=1;
  416.       break;
  417.     case (int) OPT_DELAYED:
  418.       opt_delayed=1;
  419.       break;
  420.     case (int) OPT_TABLES:
  421.       opt_databases=0;
  422.       break;
  423. #include "sslopt-case.h"
  424.     }
  425.   }
  426.   if (opt_delayed)
  427.     opt_lock=0;                /* Can't have lock with delayed */
  428.   if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
  429.         fields_terminated))
  430.   {
  431.     fprintf(stderr, "%s: You must use option --tab with --fields-...\n", my_progname);
  432.     return(1);
  433.   }
  434.  
  435.   if (enclosed && opt_enclosed)
  436.   {
  437.     fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
  438.     return(1);
  439.   }
  440.   if (replace && ignore)
  441.   {
  442.     fprintf(stderr, "%s: You can't use --ignore (-i) and --replace (-r) at the same time.\n",my_progname);
  443.     return(1);
  444.   }
  445.   if ((opt_databases || opt_alldbs) && path)
  446.   {
  447.     fprintf(stderr,
  448.         "%s: --databases or --all-databases can't be used with --tab.\n",
  449.         my_progname);
  450.     return(1);
  451.   }
  452.   if (default_charset)
  453.   {
  454.     if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
  455.       exit(1);
  456.   }
  457.   (*argc)-=optind;
  458.   (*argv)+=optind;
  459.   if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
  460.   {
  461.     usage();
  462.     return 1;
  463.   }
  464.   if (tty_password)
  465.     opt_password=get_tty_password(NullS);
  466.   return(0);
  467. } /* get_options */
  468.  
  469.  
  470. /*
  471. ** DBerror -- prints mysql error message and exits the program.
  472. */
  473. static void DBerror(MYSQL *mysql, const char *when)
  474. {
  475.   DBUG_ENTER("DBerror");
  476.   my_printf_error(0,"Got error: %d: %s %s", MYF(0),
  477.           mysql_errno(mysql), mysql_error(mysql), when);
  478.   safe_exit(EX_MYSQLERR);
  479.   DBUG_VOID_RETURN;
  480. } /* DBerror */
  481.  
  482.  
  483. static void safe_exit(int error)
  484. {
  485.   if (!first_error)
  486.     first_error= error;
  487.   if (ignore_errors)
  488.     return;
  489.   if (sock)
  490.     mysql_close(sock);
  491.   exit(error);
  492. }
  493. /* safe_exit */
  494.  
  495.  
  496. /*
  497. ** dbConnect -- connects to the host and selects DB.
  498. **        Also checks whether the tablename is a valid table name.
  499. */
  500. static int dbConnect(char *host, char *user,char *passwd)
  501. {
  502.   DBUG_ENTER("dbConnect");
  503.   if (verbose)
  504.   {
  505.     fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
  506.   }
  507.   mysql_init(&mysql_connection);
  508.   if (opt_compress)
  509.     mysql_options(&mysql_connection,MYSQL_OPT_COMPRESS,NullS);
  510. #ifdef HAVE_OPENSSL
  511.   if (opt_use_ssl)
  512.     mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
  513.           opt_ssl_capath);
  514. #endif
  515.   if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd,
  516.          NULL,opt_mysql_port,opt_mysql_unix_port,
  517.          0)))
  518.   {
  519.     DBerror(&mysql_connection, "when trying to connect");
  520.     return 1;
  521.   }
  522.   return 0;
  523. } /* dbConnect */
  524.  
  525.  
  526. /*
  527. ** dbDisconnect -- disconnects from the host.
  528. */
  529. static void dbDisconnect(char *host)
  530. {
  531.   if (verbose)
  532.     fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
  533.   mysql_close(sock);
  534. } /* dbDisconnect */
  535.  
  536.  
  537. static void unescape(FILE *file,char *pos,uint length)
  538. {
  539.   char *tmp;
  540.   DBUG_ENTER("unescape");
  541.   if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
  542.   {
  543.     ignore_errors=0;                /* Fatal error */
  544.     safe_exit(EX_MYSQLERR);            /* Force exit */
  545.   }
  546.   mysql_real_escape_string(&mysql_connection,tmp, pos, length);
  547.   fputc('\'', file);
  548.   fputs(tmp, file);
  549.   fputc('\'', file);
  550.   my_free(tmp, MYF(MY_WME));
  551.   DBUG_VOID_RETURN;
  552. } /* unescape */
  553.  
  554.  
  555. static my_bool test_if_special_chars(const char *str)
  556. {
  557. #if MYSQL_VERSION_ID >= 32300
  558.   for ( ; *str ; str++)
  559.     if (!isvar(*str) && *str != '$')
  560.       return 1;
  561. #endif
  562.   return 0;
  563. } /* test_if_special_chars */
  564.  
  565. static char *quote_name(char *name, char *buff)
  566. {
  567.   char *end;
  568.   if (!opt_quoted && !test_if_special_chars(name))
  569.     return name;
  570.   buff[0]=QUOTE_CHAR;
  571.   end=strmov(buff+1,name);
  572.   end[0]=QUOTE_CHAR;
  573.   end[1]=0;
  574.   return buff;
  575. } /* quote_name */
  576.  
  577.  
  578. /*
  579. ** getStructure -- retrievs database structure, prints out corresponding
  580. **       CREATE statement and fills out insert_pat.
  581. ** Return values:  number of fields in table, 0 if error
  582. */
  583. static uint getTableStructure(char *table, char* db)
  584. {
  585.   MYSQL_RES  *tableRes;
  586.   MYSQL_ROW  row;
  587.   my_bool    init=0;
  588.   uint       numFields;
  589.   char          *strpos, *table_name;
  590.   const char *delayed;
  591.   char          name_buff[NAME_LEN+3],table_buff[NAME_LEN+3];
  592.   FILE       *sql_file = stdout;
  593.   DBUG_ENTER("getTableStructure");
  594.  
  595.   delayed= opt_delayed ? " DELAYED " : "";
  596.  
  597.   if (verbose)
  598.     fprintf(stderr, "# Retrieving table structure for table %s...\n", table);
  599.  
  600.   sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", opt_quoted);
  601.   table_name=quote_name(table,table_buff);
  602.   if (mysql_query(sock,insert_pat))
  603.   {
  604.     /* using SHOW CREATE statement */
  605.     if (!tFlag)
  606.     {
  607.       /* Make an sql-file, if path was given iow. option -T was given */
  608.       char buff[20+FN_REFLEN];
  609.  
  610.       sprintf(buff,"show create table %s",table_name);
  611.       if (mysql_query(sock, buff))
  612.       {
  613.         fprintf(stderr, "%s: Can't get CREATE TABLE for table '%s' (%s)\n",
  614.                 my_progname, table, mysql_error(sock));
  615.         safe_exit(EX_MYSQLERR);
  616.         DBUG_RETURN(0);
  617.       }
  618.  
  619.       if (path)
  620.       {
  621.         char filename[FN_REFLEN], tmp_path[FN_REFLEN];
  622.         strmov(tmp_path,path);
  623.         convert_dirname(tmp_path);
  624.         sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
  625.                    O_WRONLY, MYF(MY_WME));
  626.         if (!sql_file)            /* If file couldn't be opened */
  627.         {
  628.           safe_exit(EX_MYSQLERR);
  629.           DBUG_RETURN(0);
  630.         }
  631.         write_heder(sql_file, db);
  632.       }
  633.       fprintf(sql_file, "\n#\n# Table structure for table '%s'\n#\n\n", table);
  634.       if (opt_drop)
  635.         fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",table_name);
  636.  
  637.       tableRes=mysql_store_result(sock);
  638.       row=mysql_fetch_row(tableRes);
  639.       fprintf(sql_file, "%s;\n", row[1]);
  640.       mysql_free_result(tableRes);
  641.     }
  642.     sprintf(insert_pat,"show fields from %s",table_name);
  643.     if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock)))
  644.     {
  645.       fprintf(stderr, "%s: Can't get info about table: '%s'\nerror: %s\n",
  646.               my_progname, table, mysql_error(sock));
  647.       safe_exit(EX_MYSQLERR);
  648.       DBUG_RETURN(0);
  649.     }
  650.  
  651.     if (cFlag)
  652.       sprintf(insert_pat, "INSERT %sINTO %s (", delayed, table_name);
  653.     else
  654.     {
  655.       sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, table_name);
  656.       if (!extended_insert)
  657.         strcat(insert_pat,"(");
  658.     }
  659.  
  660.     strpos=strend(insert_pat);
  661.     while ((row=mysql_fetch_row(tableRes)))
  662.     {
  663.       ulong *lengths=mysql_fetch_lengths(tableRes);
  664.       if (init)
  665.       {
  666.         if (cFlag)
  667.           strpos=strmov(strpos,", ");
  668.       }
  669.       init=1;
  670.       if (cFlag)
  671.         strpos=strmov(strpos,quote_name(row[SHOW_FIELDNAME],name_buff));
  672.     }
  673.     numFields = (uint) mysql_num_rows(tableRes);
  674.     mysql_free_result(tableRes);
  675.   }
  676.   else
  677.   {
  678.   /*  fprintf(stderr, "%s: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
  679.       my_progname, mysql_error(sock)); */
  680.  
  681.     sprintf(insert_pat,"show fields from %s",table_name);
  682.     if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock)))
  683.     {
  684.       fprintf(stderr, "%s: Can't get info about table: '%s'\nerror: %s\n",
  685.             my_progname, table, mysql_error(sock));
  686.       safe_exit(EX_MYSQLERR);
  687.       DBUG_RETURN(0);
  688.     }
  689.  
  690.     /* Make an sql-file, if path was given iow. option -T was given */
  691.     if (!tFlag)
  692.     {
  693.       if (path)
  694.       {
  695.         char filename[FN_REFLEN], tmp_path[FN_REFLEN];
  696.         strmov(tmp_path,path);
  697.         convert_dirname(tmp_path);
  698.         sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
  699.                  O_WRONLY, MYF(MY_WME));
  700.         if (!sql_file)            /* If file couldn't be opened */
  701.         {
  702.         safe_exit(EX_MYSQLERR);
  703.         DBUG_RETURN(0);
  704.         }
  705.         write_heder(sql_file, db);
  706.       }
  707.       fprintf(sql_file, "\n#\n# Table structure for table '%s'\n#\n\n", table);
  708.       if (opt_drop)
  709.         fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",table_name);
  710.       fprintf(sql_file, "CREATE TABLE %s (\n", table_name);
  711.     }
  712.     if (cFlag)
  713.       sprintf(insert_pat, "INSERT %sINTO %s (", delayed, table_name);
  714.     else
  715.     {
  716.       sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, table_name);
  717.       if (!extended_insert)
  718.         strcat(insert_pat,"(");
  719.     }
  720.  
  721.     strpos=strend(insert_pat);
  722.     while ((row=mysql_fetch_row(tableRes)))
  723.     {
  724.       ulong *lengths=mysql_fetch_lengths(tableRes);
  725.       if (init)
  726.       {
  727.         if (!tFlag)
  728.         fputs(",\n",sql_file);
  729.         if (cFlag)
  730.         strpos=strmov(strpos,", ");
  731.       }
  732.       init=1;
  733.       if (cFlag)
  734.         strpos=strmov(strpos,quote_name(row[SHOW_FIELDNAME],name_buff));
  735.       if (!tFlag)
  736.       {
  737.         if (opt_keywords)
  738.         fprintf(sql_file, "  %s.%s %s", table_name,
  739.             quote_name(row[SHOW_FIELDNAME],name_buff), row[SHOW_TYPE]);
  740.         else
  741.         fprintf(sql_file, "  %s %s", quote_name(row[SHOW_FIELDNAME],name_buff),
  742.             row[SHOW_TYPE]);
  743.         if (row[SHOW_DEFAULT])
  744.         {
  745.         fputs(" DEFAULT ", sql_file);
  746.         unescape(sql_file,row[SHOW_DEFAULT],lengths[SHOW_DEFAULT]);
  747.         }
  748.         if (!row[SHOW_NULL][0])
  749.         fputs(" NOT NULL", sql_file);
  750.         if (row[SHOW_EXTRA][0])
  751.         fprintf(sql_file, " %s",row[SHOW_EXTRA]);
  752.       }
  753.     }
  754.     numFields = (uint) mysql_num_rows(tableRes);
  755.     mysql_free_result(tableRes);
  756.     if (!tFlag)
  757.     {
  758.       /* Make an sql-file, if path was given iow. option -T was given */
  759.       char buff[20+FN_REFLEN];
  760.       uint keynr,primary_key;
  761.       sprintf(buff,"show keys from %s",table_name);
  762.       if (mysql_query(sock, buff))
  763.       {
  764.         fprintf(stderr, "%s: Can't get keys for table '%s' (%s)\n",
  765.               my_progname, table, mysql_error(sock));
  766.         if (sql_file != stdout)
  767.         my_fclose(sql_file, MYF(MY_WME));
  768.         safe_exit(EX_MYSQLERR);
  769.         DBUG_RETURN(0);
  770.       }
  771.  
  772.       tableRes=mysql_store_result(sock);
  773.       /* Find first which key is primary key */
  774.       keynr=0;
  775.       primary_key=INT_MAX;
  776.       while ((row=mysql_fetch_row(tableRes)))
  777.       {
  778.         if (atoi(row[3]) == 1)
  779.         {
  780.         keynr++;
  781.     #ifdef FORCE_PRIMARY_KEY
  782.         if (atoi(row[1]) == 0 && primary_key == INT_MAX)
  783.           primary_key=keynr;
  784.     #endif
  785.         if (!strcmp(row[2],"PRIMARY"))
  786.         {
  787.           primary_key=keynr;
  788.           break;
  789.         }
  790.         }
  791.       }
  792.       mysql_data_seek(tableRes,0);
  793.       keynr=0;
  794.       while ((row=mysql_fetch_row(tableRes)))
  795.       {
  796.         if (atoi(row[3]) == 1)
  797.         {
  798.         if (keynr++)
  799.           putc(')', sql_file);
  800.         if (atoi(row[1]))       /* Test if duplicate key */
  801.           /* Duplicate allowed */
  802.           fprintf(sql_file, ",\n  KEY %s (",quote_name(row[2],name_buff));
  803.         else if (keynr == primary_key)
  804.           fputs(",\n  PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
  805.         else
  806.           fprintf(sql_file, ",\n  UNIQUE %s (",quote_name(row[2],name_buff));
  807.         }
  808.         else
  809.         putc(',', sql_file);
  810.         fputs(quote_name(row[4],name_buff), sql_file);
  811.         if (row[7])
  812.         fprintf(sql_file, "(%s)",row[7]);      /* Sub key */
  813.       }
  814.       if (keynr)
  815.         putc(')', sql_file);
  816.       fputs("\n)",sql_file);
  817.  
  818.       /* Get MySQL specific create options */
  819.       if (create_options)
  820.       {
  821.         sprintf(buff,"show table status like '%s'",table);
  822.         if (mysql_query(sock, buff))
  823.         {
  824.         if (mysql_errno(sock) != ER_PARSE_ERROR)
  825.         {                    /* If old MySQL version */
  826.           if (verbose)
  827.             fprintf(stderr,
  828.                 "# Warning: Couldn't get status information for table '%s' (%s)\n",
  829.                 table,mysql_error(sock));
  830.         }
  831.         }
  832.         else if (!(tableRes=mysql_store_result(sock)) ||
  833.                !(row=mysql_fetch_row(tableRes)))
  834.         {
  835.         fprintf(stderr,
  836.             "Error: Couldn't read status information for table '%s' (%s)\n",
  837.             table,mysql_error(sock));
  838.         }
  839.         else
  840.         {
  841.         fputs("/*!",sql_file);
  842.         print_value(sql_file,tableRes,row,"type=","Type",0);
  843.         print_value(sql_file,tableRes,row,"","Create_options",0);
  844.         print_value(sql_file,tableRes,row,"comment=","Comment",1);
  845.         fputs(" */",sql_file);
  846.         }
  847.         mysql_free_result(tableRes);        /* Is always safe to free */
  848.       }
  849.       fputs(";\n", sql_file);
  850.     }
  851.   }
  852.   if (cFlag)
  853.   {
  854.     strpos=strmov(strpos,") VALUES ");
  855.     if (!extended_insert)
  856.       strpos=strmov(strpos,"(");
  857.   }
  858.   DBUG_RETURN(numFields);
  859. } /* getTableStructure */
  860.  
  861.  
  862. static char *add_load_option(char *ptr,const char *object,
  863.                  const char *statement)
  864. {
  865.   if (object)
  866.   {
  867.     ptr= strxmov(ptr," ",statement," '",NullS);
  868.     ptr= field_escape(ptr,object,(uint) strlen(object));
  869.     *ptr++= '\'';
  870.   }
  871.   return ptr;
  872. } /* add_load_option */
  873.  
  874.  
  875. /*
  876. ** Allow the user to specify field terminator strings like:
  877. ** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
  878. ** This is done by doubleing ' and add a end -\ if needed to avoid
  879. ** syntax errors from the SQL parser.
  880. */
  881.  
  882. static char *field_escape(char *to,const char *from,uint length)
  883. {
  884.   const char *end;
  885.   uint end_backslashes=0;
  886.  
  887.   for (end= from+length; from != end; from++)
  888.   {
  889.     *to++= *from;
  890.     if (*from == '\\')
  891.       end_backslashes^=1;    /* find odd number of backslashes */
  892.     else
  893.     {
  894.       if (*from == '\'' && !end_backslashes)
  895.     *to++= *from;      /* We want a duplicate of "'" for MySQL */
  896.       end_backslashes=0;
  897.     }
  898.   }
  899.   /* Add missing backslashes if user has specified odd number of backs.*/
  900.   if (end_backslashes)
  901.     *to++= '\\';
  902.   return to;
  903. } /* field_escape */
  904.  
  905.  
  906. /*
  907. ** dumpTable saves database contents as a series of INSERT statements.
  908. */
  909. static void dumpTable(uint numFields, char *table)
  910. {
  911.   char query[1024], *end, buff[256],table_buff[NAME_LEN+3];
  912.   MYSQL_RES    *res;
  913.   MYSQL_FIELD  *field;
  914.   MYSQL_ROW    row;
  915.   ulong        rownr, row_break, total_length, init_length;
  916.  
  917.   if (verbose)
  918.     fprintf(stderr, "# Sending SELECT query...\n");
  919.   if (path)
  920.   {
  921.     char filename[FN_REFLEN], tmp_path[FN_REFLEN];
  922.     strmov(tmp_path, path);
  923.     convert_dirname(tmp_path);
  924.     my_load_path(tmp_path, tmp_path, NULL);
  925.     fn_format(filename, table, tmp_path, ".txt", 4);
  926.     my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if
  927.                     filename wasn't deleted */
  928.     to_unix_path(filename);
  929.     sprintf(query, "SELECT * INTO OUTFILE '%s'", filename);
  930.     end= strend(query);
  931.     if (replace)
  932.       end= strmov(end, " REPLACE");
  933.     if (ignore)
  934.       end= strmov(end, " IGNORE");
  935.  
  936.     if (fields_terminated || enclosed || opt_enclosed || escaped)
  937.       end= strmov(end, " FIELDS");
  938.     end= add_load_option(end, fields_terminated, " TERMINATED BY");
  939.     end= add_load_option(end, enclosed, " ENCLOSED BY");
  940.     end= add_load_option(end, opt_enclosed, " OPTIONALLY ENCLOSED BY");
  941.     end= add_load_option(end, escaped, " ESCAPED BY");
  942.     end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
  943.     *end= '\0';
  944.  
  945.     sprintf(buff," FROM %s",table);
  946.     end= strmov(end,buff);
  947.     if (where)
  948.       end= strxmov(end, " WHERE ",where,NullS);
  949.     if (mysql_query(sock, query))
  950.     {
  951.       DBerror(sock, "when executing 'SELECT INTO OUTFILE'");
  952.       return;
  953.     }
  954.   }
  955.   else
  956.   {
  957.     printf("\n#\n# Dumping data for table '%s'\n", table);
  958.     sprintf(query, "SELECT * FROM %s", quote_name(table,table_buff));
  959.     if (where)
  960.     {
  961.       printf("# WHERE:  %s\n",where);
  962.       strxmov(strend(query), " WHERE ",where,NullS);
  963.     }
  964.     puts("#\n");
  965.  
  966.     if (mysql_query(sock, query))
  967.     {
  968.       DBerror(sock, "when retrieving data from server");
  969.       return;
  970.     }
  971.     if (quick)
  972.       res=mysql_use_result(sock);
  973.     else
  974.       res=mysql_store_result(sock);
  975.     if (!res)
  976.     {
  977.       DBerror(sock, "when retrieving data from server");
  978.       return;
  979.     }
  980.     if (verbose)
  981.       fprintf(stderr, "# Retrieving rows...\n");
  982.     if (mysql_num_fields(res) != numFields)
  983.     {
  984.       fprintf(stderr,"%s: Error in field count for table: '%s' !  Aborting.\n",
  985.           my_progname,table);
  986.       safe_exit(EX_CONSCHECK);
  987.       return;
  988.     }
  989.  
  990.     if (opt_lock)
  991.       printf("LOCK TABLES %s WRITE;\n", quote_name(table,table_buff));
  992.  
  993.     total_length=net_buffer_length;        /* Force row break */
  994.     row_break=0;
  995.     rownr=0;
  996.     init_length=(uint) strlen(insert_pat)+4;
  997.  
  998.     while ((row=mysql_fetch_row(res)))
  999.     {
  1000.       uint i;
  1001.       ulong *lengths=mysql_fetch_lengths(res);
  1002.       rownr++;
  1003.       if (!extended_insert)
  1004.     fputs(insert_pat,stdout);
  1005.       mysql_field_seek(res,0);
  1006.  
  1007.       for (i = 0; i < mysql_num_fields(res); i++)
  1008.       {
  1009.     if (!(field = mysql_fetch_field(res)))
  1010.     {
  1011.       sprintf(query,"%s: Not enough fields from table '%s'! Aborting.\n",
  1012.           my_progname,table);
  1013.       fputs(query,stderr);
  1014.       safe_exit(EX_CONSCHECK);
  1015.       return;
  1016.     }
  1017.     if (extended_insert)
  1018.     {
  1019.       ulong length = lengths[i];
  1020.       if (i == 0)
  1021.         dynstr_set(&extended_row,"(");
  1022.       else
  1023.         dynstr_append(&extended_row,",");
  1024.  
  1025.       if (row[i])
  1026.       {
  1027.         if (length)
  1028.         {
  1029.           if (!IS_NUM_FIELD(field))
  1030.           {
  1031.         if (dynstr_realloc(&extended_row,length * 2+2))
  1032.         {
  1033.           fputs("Aborting dump (out of memory)",stderr);
  1034.           safe_exit(EX_EOM);
  1035.         }
  1036.         dynstr_append(&extended_row,"\'");
  1037.         extended_row.length +=
  1038.           mysql_real_escape_string(&mysql_connection,
  1039.                        &extended_row.str[extended_row.length],row[i],length);
  1040.         extended_row.str[extended_row.length]='\0';
  1041.         dynstr_append(&extended_row,"\'");
  1042.           }
  1043.           else
  1044.         dynstr_append(&extended_row,row[i]);
  1045.         }
  1046.         else
  1047.           dynstr_append(&extended_row,"\'\'");
  1048.       }
  1049.       else if (dynstr_append(&extended_row,"NULL"))
  1050.       {
  1051.         fputs("Aborting dump (out of memory)",stderr);
  1052.         safe_exit(EX_EOM);
  1053.       }
  1054.     }
  1055.     else
  1056.     {
  1057.       if (i)
  1058.         putchar(',');
  1059.       if (row[i])
  1060.       {
  1061.         if (!IS_NUM_FIELD(field))
  1062.           unescape(stdout, row[i], lengths[i]);
  1063.         else
  1064.           fputs(row[i],stdout);
  1065.       }
  1066.       else
  1067.       {
  1068.         fputs("NULL",stdout);
  1069.       }
  1070.     }
  1071.       }
  1072.  
  1073.       if (extended_insert)
  1074.       {
  1075.     ulong row_length;
  1076.     dynstr_append(&extended_row,")");
  1077.         row_length = 2 + extended_row.length;
  1078.         if (total_length + row_length < net_buffer_length)
  1079.         {
  1080.       total_length += row_length;
  1081.       putchar(',');                /* Always row break */
  1082.       fputs(extended_row.str,stdout);
  1083.     }
  1084.         else
  1085.         {
  1086.       if (row_break)
  1087.         puts(";");
  1088.       row_break=1;                /* This is first row */
  1089.       fputs(insert_pat,stdout);
  1090.       fputs(extended_row.str,stdout);
  1091.       total_length = row_length+init_length;
  1092.         }
  1093.       }
  1094.       else
  1095.       {
  1096.     puts(");");
  1097.       }
  1098.     }
  1099.     if (extended_insert && row_break)
  1100.       puts(";");                /* If not empty table */
  1101.     fflush(stdout);
  1102.     if (mysql_errno(sock))
  1103.     {
  1104.       sprintf(query,"%s: Error %d: %s when dumping table '%s' at row: %ld\n",
  1105.           my_progname,
  1106.           mysql_errno(sock),
  1107.           mysql_error(sock),
  1108.           table,
  1109.           rownr);
  1110.       fputs(query,stderr);
  1111.       safe_exit(EX_CONSCHECK);
  1112.       return;
  1113.     }
  1114.     if (opt_lock)
  1115.       puts("UNLOCK TABLES;");
  1116.     mysql_free_result(res);
  1117.   }
  1118. } /* dumpTable */
  1119.  
  1120.  
  1121. static char *getTableName(int reset)
  1122. {
  1123.   static MYSQL_RES *res = NULL;
  1124.   MYSQL_ROW    row;
  1125.  
  1126.   if (!res)
  1127.   {
  1128.     if (!(res = mysql_list_tables(sock,NullS)))
  1129.       return(NULL);
  1130.   }
  1131.   if ((row = mysql_fetch_row(res)))
  1132.     return((char*) row[0]);
  1133.  
  1134.   if (reset)
  1135.     mysql_data_seek(res,0);      /* We want to read again */
  1136.   else
  1137.   {
  1138.     mysql_free_result(res);
  1139.     res = NULL;
  1140.   }
  1141.   return(NULL);
  1142. } /* getTableName */
  1143.  
  1144.  
  1145. static int dump_all_databases()
  1146. {
  1147.   MYSQL_ROW row;
  1148.   MYSQL_RES *tableres;
  1149.   int result=0;
  1150.  
  1151.   if (mysql_query(sock, "SHOW DATABASES") ||
  1152.       !(tableres = mysql_store_result(sock)))
  1153.   {
  1154.     my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
  1155.             MYF(0), mysql_error(sock));
  1156.     return 1;
  1157.   }
  1158.   while ((row = mysql_fetch_row(tableres)))
  1159.   {
  1160.     if (dump_all_tables_in_db(row[0]))
  1161.       result=1;
  1162.   }
  1163.   return result;
  1164. }
  1165. /* dump_all_databases */
  1166.  
  1167.  
  1168. static int dump_databases(char **db_names)
  1169. {
  1170.   int result=0;
  1171.   for ( ; *db_names ; db_names++)
  1172.   {
  1173.     if (dump_all_tables_in_db(*db_names))
  1174.       result=1;
  1175.   }
  1176.   return result;
  1177. } /* dump_databases */
  1178.  
  1179.  
  1180. static int init_dumping(char *database)
  1181. {
  1182.   if (mysql_select_db(sock, database))
  1183.   {
  1184.     DBerror(sock, "when selecting the database");
  1185.     return 1;            /* If --force */
  1186.   }
  1187.   if (!path)
  1188.   {
  1189.     if (opt_databases || opt_alldbs)
  1190.     {
  1191.       printf("\n#\n# Current Database: %s\n#\n", database);
  1192.       if (!opt_create_db)
  1193.     printf("\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n", database);
  1194.       printf("\nUSE %s;\n", database);
  1195.     }
  1196.   }
  1197.   if (extended_insert)
  1198.     if (init_dynamic_string(&extended_row, "", 1024, 1024))
  1199.       exit(EX_EOM);
  1200.   return 0;
  1201. } /* init_dumping */
  1202.  
  1203.  
  1204. static int dump_all_tables_in_db(char *database)
  1205. {
  1206.   char *table;
  1207.   uint numrows;
  1208.  
  1209.   if (init_dumping(database))
  1210.     return 1;
  1211.   if (lock_tables)
  1212.   {
  1213.     DYNAMIC_STRING query;
  1214.     init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
  1215.     for (numrows=0 ; (table = getTableName(1)) ; numrows++)
  1216.     {
  1217.       dynstr_append(&query, table);
  1218.       dynstr_append(&query, " READ /*!32311 LOCAL */,");
  1219.     }
  1220.     if (numrows && mysql_real_query(sock, query.str, query.length-1))
  1221.       DBerror(sock, "when using LOCK TABLES");
  1222.             /* We shall continue here, if --force was given */
  1223.     dynstr_free(&query);
  1224.   }
  1225.   if (flush_logs)
  1226.   {
  1227.     if (mysql_refresh(sock, REFRESH_LOG))
  1228.       DBerror(sock, "when doing refresh");
  1229.            /* We shall continue here, if --force was given */
  1230.   }
  1231.   while ((table = getTableName(0)))
  1232.   {
  1233.     numrows = getTableStructure(table, database);
  1234.     if (!dFlag && numrows > 0)
  1235.       dumpTable(numrows,table);
  1236.   }
  1237.   if (lock_tables)
  1238.     mysql_query(sock,"UNLOCK_TABLES");
  1239.   return 0;
  1240. } /* dump_all_tables_in_db */
  1241.  
  1242.  
  1243.  
  1244. static int dump_selected_tables(char *db, char **table_names, int tables)
  1245. {
  1246.   uint numrows;
  1247.  
  1248.   if (init_dumping(db))
  1249.     return 1;
  1250.   if (lock_tables)
  1251.   {
  1252.     DYNAMIC_STRING query;
  1253.     int i;
  1254.  
  1255.     init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
  1256.     for (i=0 ; i < tables ; i++)
  1257.     {
  1258.       dynstr_append(&query, table_names[i]);
  1259.       dynstr_append(&query, " READ /*!32311 LOCAL */,");
  1260.     }
  1261.     if (mysql_real_query(sock, query.str, query.length-1))
  1262.       DBerror(sock, "when doing LOCK TABLES");
  1263.        /* We shall countinue here, if --force was given */
  1264.     dynstr_free(&query);
  1265.   }
  1266.   if (flush_logs)
  1267.   {
  1268.     if (mysql_refresh(sock, REFRESH_LOG))
  1269.       DBerror(sock, "when doing refresh");
  1270.      /* We shall countinue here, if --force was given */
  1271.   }
  1272.   for (; tables > 0 ; tables-- , table_names++)
  1273.   {
  1274.     numrows = getTableStructure(*table_names, db);
  1275.     if (!dFlag && numrows > 0)
  1276.       dumpTable(numrows, *table_names);
  1277.   }
  1278.   if (lock_tables)
  1279.     mysql_query(sock,"UNLOCK_TABLES");
  1280.   return 0;
  1281. } /* dump_selected_tables */
  1282.  
  1283.  
  1284. /* Print a value with a prefix on file */
  1285. static void print_value(FILE *file, MYSQL_RES  *result, MYSQL_ROW row,
  1286.             const char *prefix, const char *name,
  1287.             int string_value)
  1288. {
  1289.   MYSQL_FIELD    *field;
  1290.   mysql_field_seek(result, 0);
  1291.  
  1292.   for ( ; (field = mysql_fetch_field(result)) ; row++)
  1293.   {
  1294.     if (!strcmp(field->name,name))
  1295.     {
  1296.       if (row[0] && row[0][0] && strcmp(row[0],"0")) /* Skip default */
  1297.       {
  1298.     fputc(' ',file);
  1299.     fputs(prefix, file);
  1300.     if (string_value)
  1301.       unescape(file,row[0],(uint) strlen(row[0]));
  1302.     else
  1303.       fputs(row[0], file);
  1304.     return;
  1305.       }
  1306.     }
  1307.   }
  1308.   return;                    /* This shouldn't happen */
  1309. } /* print_value */
  1310.  
  1311.  
  1312. int main(int argc, char **argv)
  1313. {
  1314.   MY_INIT(argv[0]);
  1315.   /*
  1316.   ** Check out the args
  1317.   */
  1318.   if (get_options(&argc, &argv))
  1319.   {
  1320.     my_end(0);
  1321.     exit(EX_USAGE);
  1322.   }
  1323.   if (dbConnect(current_host, current_user, opt_password))
  1324.     exit(EX_MYSQLERR);
  1325.   if (!path)
  1326.     write_heder(stdout, *argv);
  1327.  
  1328.    if (opt_first_slave)
  1329.    {
  1330.      lock_tables=0;                /* No other locks needed */
  1331.      if (mysql_query(sock, "FLUSH TABLES WITH READ LOCK"))
  1332.      {
  1333.        my_printf_error(0, "Error: Couldn't execute 'FLUSH TABLES WITH READ LOCK': %s",
  1334.                MYF(0), mysql_error(sock));
  1335.        my_end(0);
  1336.        return(first_error);
  1337.      }
  1338.    }
  1339.   if (opt_alldbs)
  1340.     dump_all_databases();
  1341.   /* Only one database and selected table(s) */
  1342.   else if (argc > 1 && !opt_databases)
  1343.     dump_selected_tables(*argv, (argv + 1), (argc - 1));
  1344.   /* One or more databases, all tables */
  1345.   else
  1346.     dump_databases(argv);
  1347.  
  1348.   if (opt_first_slave)
  1349.   {
  1350.     if (mysql_query(sock, "FLUSH MASTER"))
  1351.     {
  1352.       my_printf_error(0, "Error: Couldn't execute 'FLUSH MASTER': %s",
  1353.               MYF(0), mysql_error(sock));
  1354.     }
  1355.     if (mysql_query(sock, "UNLOCK TABLES"))
  1356.     {
  1357.       my_printf_error(0, "Error: Couldn't execute 'UNLOCK TABLES': %s",
  1358.               MYF(0), mysql_error(sock));
  1359.    }
  1360.   }
  1361.   dbDisconnect(current_host);
  1362.   puts("");
  1363.   my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
  1364.   if (extended_insert)
  1365.     dynstr_free(&extended_row);
  1366.   my_end(0);
  1367.   return(first_error);
  1368. } /* main */
  1369.