~drizzle-trunk/drizzle/development

206.3.1 by Patrick Galbraith
Most everything working with client rename
1
/* Copyright (C) 2008 Drizzle development team
1 by brian
clean slate
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; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
206.3.1 by Patrick Galbraith
Most everything working with client rename
16
/* By Jani Tolonen, 2001-04-20, MySQL, DRIZZLE Development Team */
1 by brian
clean slate
17
18
#define CHECK_VERSION "2.5.0"
19
20
#include "client_priv.h"
21
#include <m_ctype.h>
77.1.39 by Monty Taylor
More mysql->drizzle renaming.
22
#include <drizzle_version.h>
1 by brian
clean slate
23
#include <mysqld_error.h>
24
25
/* Exit codes */
26
27
#define EX_USAGE 1
28
#define EX_MYSQLERR 2
29
206.3.1 by Patrick Galbraith
Most everything working with client rename
30
static DRIZZLE drizzle_connection, *sock = 0;
143 by Brian Aker
Bool cleanup.
31
static bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
1 by brian
clean slate
32
               opt_compress = 0, opt_databases = 0, opt_fast = 0,
33
               opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
34
               opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
35
               tty_password= 0, opt_frm= 0, debug_info_flag= 0, debug_check_flag= 0,
36
               opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0,
37
               opt_write_binlog= 1;
38
static uint verbose = 0, opt_mysql_port=0;
39
static int my_end_arg;
40
static char * opt_mysql_unix_port = 0;
206.3.1 by Patrick Galbraith
Most everything working with client rename
41
static char *opt_password = 0, *current_user = 0,
42
      *default_charset = (char *)MYSQL_DEFAULT_CHARSET_NAME,
43
      *current_host = 0;
1 by brian
clean slate
44
static int first_error = 0;
45
DYNAMIC_ARRAY tables4repair;
46
static uint opt_protocol=0;
47
static CHARSET_INFO *charset_info= &my_charset_latin1;
48
49
enum operations { DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
50
51
static struct my_option my_long_options[] =
52
{
53
  {"all-databases", 'A',
54
   "Check all the databases. This will be same as  --databases with all databases selected.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
55
   (char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1 by brian
clean slate
56
   0, 0},
57
  {"analyze", 'a', "Analyze given tables.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
58
   0, 0, 0, 0},
59
  {"all-in-1", '1',
60
   "Instead of issuing one query for each table, use one query per database, naming all tables in the database in a comma-separated list.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
61
   (char**) &opt_all_in_1, (char**) &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1 by brian
clean slate
62
   0, 0, 0},
63
  {"auto-repair", OPT_AUTO_REPAIR,
64
   "If a checked table is corrupted, automatically fix it. Repairing will be done after all tables have been checked, if corrupted ones were found.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
65
   (char**) &opt_auto_repair, (char**) &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0,
1 by brian
clean slate
66
   0, 0, 0, 0, 0},
67
  {"character-sets-dir", OPT_CHARSETS_DIR,
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
68
   "Directory where character sets are.", (char**) &charsets_dir,
69
   (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
70
  {"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
71
   0, 0, 0, 0},
72
  {"check-only-changed", 'C',
73
   "Check only tables that have changed since last check or haven't been closed properly.",
74
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
75
  {"check-upgrade", 'g',
76
   "Check tables for version-dependent changes. May be used with --auto-repair to correct tables requiring version-dependent updates.",
77
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
78
  {"compress", OPT_COMPRESS, "Use compression in server/client protocol.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
79
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1 by brian
clean slate
80
   0, 0, 0},
81
  {"databases", 'B',
82
   "To check several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
83
   (char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG,
1 by brian
clean slate
84
   0, 0, 0, 0, 0, 0},
85
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
86
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
1 by brian
clean slate
87
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
88
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
89
   (char**) &debug_info_flag, (char**) &debug_info_flag,
1 by brian
clean slate
90
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
91
  {"default-character-set", OPT_DEFAULT_CHARSET,
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
92
   "Set the default character set.", (char**) &default_charset,
93
   (char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
94
  {"fast",'F', "Check only tables that haven't been closed properly.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
95
   (char**) &opt_fast, (char**) &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
1 by brian
clean slate
96
   0},
97
  {"fix-db-names", OPT_FIX_DB_NAMES, "Fix database names.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
98
    (char**) &opt_fix_db_names, (char**) &opt_fix_db_names,
1 by brian
clean slate
99
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
100
  {"fix-table-names", OPT_FIX_TABLE_NAMES, "Fix table names.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
101
    (char**) &opt_fix_table_names, (char**) &opt_fix_table_names,
1 by brian
clean slate
102
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
103
  {"force", 'f', "Continue even if we get an sql-error.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
104
   (char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
1 by brian
clean slate
105
   0, 0, 0, 0},
106
  {"extended", 'e',
107
   "If you are using this option with CHECK TABLE, it will ensure that the table is 100 percent consistent, but will take a long time. If you are using this option with REPAIR TABLE, it will force using old slow repair with keycache method, instead of much faster repair by sorting.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
108
   (char**) &opt_extended, (char**) &opt_extended, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1 by brian
clean slate
109
   0, 0, 0},
110
  {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
111
   NO_ARG, 0, 0, 0, 0, 0, 0},
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
112
  {"host",'h', "Connect to host.", (char**) &current_host,
113
   (char**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
114
  {"medium-check", 'm',
115
   "Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.",
116
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
117
  {"write-binlog", OPT_WRITE_BINLOG,
118
   "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Use --skip-write-binlog when commands should not be sent to replication slaves.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
119
   (char**) &opt_write_binlog, (char**) &opt_write_binlog, 0, GET_BOOL, NO_ARG,
1 by brian
clean slate
120
   1, 0, 0, 0, 0, 0},
121
  {"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
122
   0, 0},
123
  {"password", 'p',
124
   "Password to use when connecting to server. If password is not given it's solicited on the tty.",
125
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
126
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
127
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
128
#if MYSQL_PORT_DEFAULT == 0
129
   "/etc/services, "
130
#endif
131
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
132
   (char**) &opt_mysql_port,
133
   (char**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
1 by brian
clean slate
134
   0},
206.3.1 by Patrick Galbraith
Most everything working with client rename
135
  {"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
1 by brian
clean slate
136
   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
137
  {"quick", 'q',
138
   "If you are using this option with CHECK TABLE, it prevents the check from scanning the rows to check for wrong links. This is the fastest check. If you are using this option with REPAIR TABLE, it will try to repair only the index tree. This is the fastest repair method for a table.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
139
   (char**) &opt_quick, (char**) &opt_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
1 by brian
clean slate
140
   0},
141
  {"repair", 'r',
142
   "Can fix almost anything except unique keys that aren't unique.",
143
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
144
  {"silent", 's', "Print only error messages.", (char**) &opt_silent,
145
   (char**) &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
146
  {"socket", 'S', "Socket file to use for connection.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
147
   (char**) &opt_mysql_unix_port, (char**) &opt_mysql_unix_port, 0, GET_STR,
1 by brian
clean slate
148
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
149
  {"tables", OPT_TABLES, "Overrides option --databases (-B).", 0, 0, 0,
150
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
151
  {"use-frm", OPT_FRM,
152
   "When used with REPAIR, get table structure from .frm file, so the table can be repaired even if .MYI header is corrupted.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
153
   (char**) &opt_frm, (char**) &opt_frm, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
1 by brian
clean slate
154
   0},
155
#ifndef DONT_ALLOW_USER_CHANGE
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
156
  {"user", 'u', "User for login if not current user.", (char**) &current_user,
157
   (char**) &current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
158
#endif
159
  {"verbose", 'v', "Print info about the various stages.", 0, 0, 0, GET_NO_ARG,
160
   NO_ARG, 0, 0, 0, 0, 0, 0},
161
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
162
   NO_ARG, 0, 0, 0, 0, 0, 0},
163
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
164
};
165
166
static const char *load_default_groups[] = { "mysqlcheck", "client", 0 };
167
168
169
static void print_version(void);
170
static void usage(void);
171
static int get_options(int *argc, char ***argv);
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
172
static int process_all_databases(void);
1 by brian
clean slate
173
static int process_databases(char **db_names);
174
static int process_selected_tables(char *db, char **table_names, int tables);
175
static int process_all_tables_in_db(char *database);
176
static int process_one_db(char *database);
177
static int use_db(char *database);
178
static int handle_request_for_tables(char *tables, uint length);
179
static int dbConnect(char *host, char *user,char *passwd);
180
static void dbDisconnect(char *host);
206.3.1 by Patrick Galbraith
Most everything working with client rename
181
static void DBerror(DRIZZLE *drizzle, const char *when);
1 by brian
clean slate
182
static void safe_exit(int error);
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
183
static void print_result(void);
1 by brian
clean slate
184
static uint fixed_name_length(const char *name);
185
static char *fix_table_name(char *dest, char *src);
186
int what_to_do = 0;
187
188
static void print_version(void)
189
{
190
  printf("%s  Ver %s Distrib %s, for %s (%s)\n", my_progname, CHECK_VERSION,
191
   MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
192
} /* print_version */
193
194
static void usage(void)
195
{
196
  print_version();
197
  puts("By Jani Tolonen, 2001-04-20, MySQL Development Team\n");
198
  puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n");
199
  puts("and you are welcome to modify and redistribute it under the GPL license.\n");
200
  puts("This program can be used to CHECK (-c,-m,-C), REPAIR (-r), ANALYZE (-a)");
201
  puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be");
202
  puts("used at the same time. Not all options are supported by all storage engines.");
206.3.1 by Patrick Galbraith
Most everything working with client rename
203
  puts("Please consult the Drizzle manual for latest information about the");
1 by brian
clean slate
204
  puts("above. The options -c,-r,-a and -o are exclusive to each other, which");
205
  puts("means that the last option will be used, if several was specified.\n");
206
  puts("The option -c will be used by default, if none was specified. You");
207
  puts("can change the default behavior by making a symbolic link, or");
208
  puts("copying this file somewhere with another name, the alternatives are:");
209
  puts("mysqlrepair:   The default option will be -r");
210
  puts("mysqlanalyze:  The default option will be -a");
211
  puts("mysqloptimize: The default option will be -o\n");
212
  printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
213
  printf("OR     %s [OPTIONS] --databases DB1 [DB2 DB3...]\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
214
   my_progname);
1 by brian
clean slate
215
  printf("OR     %s [OPTIONS] --all-databases\n", my_progname);
216
  print_defaults("my", load_default_groups);
217
  my_print_help(my_long_options);
218
  my_print_variables(my_long_options);
219
} /* usage */
220
143 by Brian Aker
Bool cleanup.
221
static bool
1 by brian
clean slate
222
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
206.3.1 by Patrick Galbraith
Most everything working with client rename
223
         char *argument)
1 by brian
clean slate
224
{
225
  switch(optid) {
226
  case 'a':
227
    what_to_do = DO_ANALYZE;
228
    break;
229
  case 'c':
230
    what_to_do = DO_CHECK;
231
    break;
232
  case 'C':
233
    what_to_do = DO_CHECK;
234
    opt_check_only_changed = 1;
235
    break;
236
  case 'I': /* Fall through */
237
  case '?':
238
    usage();
239
    exit(0);
240
  case 'm':
241
    what_to_do = DO_CHECK;
242
    opt_medium_check = 1;
243
    break;
244
  case 'o':
245
    what_to_do = DO_OPTIMIZE;
246
    break;
247
  case OPT_FIX_DB_NAMES:
248
    what_to_do= DO_UPGRADE;
249
    default_charset= (char*) "utf8";
250
    opt_databases= 1;
251
    break;
252
  case OPT_FIX_TABLE_NAMES:
253
    what_to_do= DO_UPGRADE;
254
    default_charset= (char*) "utf8";
255
    break;
256
  case 'p':
257
    if (argument)
258
    {
259
      char *start = argument;
260
      my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
261
      opt_password = my_strdup(argument, MYF(MY_FAE));
206.3.1 by Patrick Galbraith
Most everything working with client rename
262
      while (*argument) *argument++= 'x';    /* Destroy argument */
1 by brian
clean slate
263
      if (*start)
206.3.1 by Patrick Galbraith
Most everything working with client rename
264
  start[1] = 0;                             /* Cut length of argument */
1 by brian
clean slate
265
      tty_password= 0;
266
    }
267
    else
268
      tty_password = 1;
269
    break;
270
  case 'r':
271
    what_to_do = DO_REPAIR;
272
    break;
273
  case 'g':
274
    what_to_do= DO_CHECK;
275
    opt_upgrade= 1;
276
    break;
277
  case OPT_TABLES:
278
    opt_databases = 0;
279
    break;
280
  case 'v':
281
    verbose++;
282
    break;
283
  case 'V': print_version(); exit(0);
206.3.1 by Patrick Galbraith
Most everything working with client rename
284
  case OPT_DRIZZLE_PROTOCOL:
1 by brian
clean slate
285
    opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
286
                                    opt->name);
287
    break;
288
  }
289
  return 0;
290
}
291
292
293
static int get_options(int *argc, char ***argv)
294
{
295
  int ho_error;
296
297
  if (*argc == 1)
298
  {
299
    usage();
300
    exit(0);
301
  }
302
303
  load_defaults("my", load_default_groups, argc, argv);
304
305
  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
306
    exit(ho_error);
307
308
  if (!what_to_do)
309
  {
310
    int pnlen = strlen(my_progname);
311
312
    if (pnlen < 6) /* name too short */
313
      what_to_do = DO_CHECK;
314
    else if (!strcmp("repair", my_progname + pnlen - 6))
315
      what_to_do = DO_REPAIR;
316
    else if (!strcmp("analyze", my_progname + pnlen - 7))
317
      what_to_do = DO_ANALYZE;
318
    else if  (!strcmp("optimize", my_progname + pnlen - 8))
319
      what_to_do = DO_OPTIMIZE;
320
    else
321
      what_to_do = DO_CHECK;
322
  }
323
324
  /* TODO: This variable is not yet used */
325
  if (strcmp(default_charset, charset_info->csname) &&
206.3.1 by Patrick Galbraith
Most everything working with client rename
326
      !(charset_info= get_charset_by_csname(default_charset,
327
                MY_CS_PRIMARY, MYF(MY_WME))))
1 by brian
clean slate
328
      exit(1);
329
  if (*argc > 0 && opt_alldbs)
330
  {
331
    printf("You should give only options, no arguments at all, with option\n");
332
    printf("--all-databases. Please see %s --help for more information.\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
333
     my_progname);
1 by brian
clean slate
334
    return 1;
335
  }
336
  if (*argc < 1 && !opt_alldbs)
337
  {
338
    printf("You forgot to give the arguments! Please see %s --help\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
339
     my_progname);
1 by brian
clean slate
340
    printf("for more information.\n");
341
    return 1;
342
  }
343
  if (tty_password)
344
    opt_password = get_tty_password(NullS);
345
  if (debug_info_flag)
346
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
347
  if (debug_check_flag)
348
    my_end_arg= MY_CHECK_ERROR;
349
  return(0);
350
} /* get_options */
351
352
353
static int process_all_databases()
354
{
206.3.1 by Patrick Galbraith
Most everything working with client rename
355
  DRIZZLE_ROW row;
356
  DRIZZLE_RES *tableres;
1 by brian
clean slate
357
  int result = 0;
358
206.3.1 by Patrick Galbraith
Most everything working with client rename
359
  if (drizzle_query(sock, "SHOW DATABASES") ||
360
      !(tableres = drizzle_store_result(sock)))
1 by brian
clean slate
361
  {
362
    my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
206.3.1 by Patrick Galbraith
Most everything working with client rename
363
        MYF(0), drizzle_error(sock));
1 by brian
clean slate
364
    return 1;
365
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
366
  while ((row = drizzle_fetch_row(tableres)))
1 by brian
clean slate
367
  {
368
    if (process_one_db(row[0]))
369
      result = 1;
370
  }
371
  return result;
372
}
373
/* process_all_databases */
374
375
376
static int process_databases(char **db_names)
377
{
378
  int result = 0;
379
  for ( ; *db_names ; db_names++)
380
  {
381
    if (process_one_db(*db_names))
382
      result = 1;
383
  }
384
  return result;
385
} /* process_databases */
386
387
388
static int process_selected_tables(char *db, char **table_names, int tables)
389
{
390
  if (use_db(db))
391
    return 1;
392
  if (opt_all_in_1)
393
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
394
    /*
1 by brian
clean slate
395
      We need table list in form `a`, `b`, `c`
396
      that's why we need 2 more chars added to to each table name
397
      space is for more readable output in logs and in case of error
206.3.1 by Patrick Galbraith
Most everything working with client rename
398
    */   
1 by brian
clean slate
399
    char *table_names_comma_sep, *end;
400
    int i, tot_length = 0;
401
402
    for (i = 0; i < tables; i++)
403
      tot_length+= fixed_name_length(*(table_names + i)) + 2;
404
405
    if (!(table_names_comma_sep = (char *)
206.3.1 by Patrick Galbraith
Most everything working with client rename
406
    my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
1 by brian
clean slate
407
      return 1;
408
409
    for (end = table_names_comma_sep + 1; tables > 0;
206.3.1 by Patrick Galbraith
Most everything working with client rename
410
   tables--, table_names++)
1 by brian
clean slate
411
    {
412
      end= fix_table_name(end, *table_names);
413
      *end++= ',';
414
    }
415
    *--end = 0;
416
    handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1);
417
    my_free(table_names_comma_sep, MYF(0));
418
  }
419
  else
420
    for (; tables > 0; tables--, table_names++)
421
      handle_request_for_tables(*table_names, fixed_name_length(*table_names));
422
  return 0;
423
} /* process_selected_tables */
424
425
426
static uint fixed_name_length(const char *name)
427
{
428
  const char *p;
429
  uint extra_length= 2;  /* count the first/last backticks */
206.3.1 by Patrick Galbraith
Most everything working with client rename
430
 
1 by brian
clean slate
431
  for (p= name; *p; p++)
432
  {
433
    if (*p == '`')
434
      extra_length++;
435
    else if (*p == '.')
436
      extra_length+= 2;
437
  }
438
  return (p - name) + extra_length;
439
}
440
441
442
static char *fix_table_name(char *dest, char *src)
443
{
444
  *dest++= '`';
445
  for (; *src; src++)
446
  {
447
    switch (*src) {
448
    case '.':            /* add backticks around '.' */
449
      *dest++= '`';
450
      *dest++= '.';
451
      *dest++= '`';
452
      break;
453
    case '`':            /* escape backtick character */
454
      *dest++= '`';
455
      /* fall through */
456
    default:
457
      *dest++= *src;
458
    }
459
  }
460
  *dest++= '`';
461
  return dest;
462
}
463
464
465
static int process_all_tables_in_db(char *database)
466
{
206.3.1 by Patrick Galbraith
Most everything working with client rename
467
  DRIZZLE_RES *res;
468
  DRIZZLE_ROW row;
1 by brian
clean slate
469
  uint num_columns;
470
471
  if (use_db(database))
472
    return 1;
206.3.1 by Patrick Galbraith
Most everything working with client rename
473
  if (drizzle_query(sock, "SHOW /*!50002 FULL*/ TABLES") ||
474
  !((res= drizzle_store_result(sock))))
1 by brian
clean slate
475
    return 1;
476
206.3.1 by Patrick Galbraith
Most everything working with client rename
477
  num_columns= drizzle_num_fields(res);
1 by brian
clean slate
478
479
  if (opt_all_in_1)
480
  {
481
    /*
482
      We need table list in form `a`, `b`, `c`
483
      that's why we need 2 more chars added to to each table name
484
      space is for more readable output in logs and in case of error
485
     */
486
487
    char *tables, *end;
488
    uint tot_length = 0;
489
206.3.1 by Patrick Galbraith
Most everything working with client rename
490
    while ((row = drizzle_fetch_row(res)))
1 by brian
clean slate
491
      tot_length+= fixed_name_length(row[0]) + 2;
206.3.1 by Patrick Galbraith
Most everything working with client rename
492
    drizzle_data_seek(res, 0);
1 by brian
clean slate
493
494
    if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
495
    {
206.3.1 by Patrick Galbraith
Most everything working with client rename
496
      drizzle_free_result(res);
1 by brian
clean slate
497
      return 1;
498
    }
206.3.1 by Patrick Galbraith
Most everything working with client rename
499
    for (end = tables + 1; (row = drizzle_fetch_row(res)) ;)
1 by brian
clean slate
500
    {
501
      if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
502
        continue;
503
504
      end= fix_table_name(end, row[0]);
505
      *end++= ',';
506
    }
507
    *--end = 0;
508
    if (tot_length)
509
      handle_request_for_tables(tables + 1, tot_length - 1);
510
    my_free(tables, MYF(0));
511
  }
512
  else
513
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
514
    while ((row = drizzle_fetch_row(res)))
1 by brian
clean slate
515
    {
516
      /* Skip views if we don't perform renaming. */
517
      if ((what_to_do != DO_UPGRADE) && (num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
518
        continue;
519
520
      handle_request_for_tables(row[0], fixed_name_length(row[0]));
521
    }
522
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
523
  drizzle_free_result(res);
1 by brian
clean slate
524
  return 0;
525
} /* process_all_tables_in_db */
526
527
528
529
static int fix_table_storage_name(const char *name)
530
{
531
  char qbuf[100 + NAME_LEN*4];
532
  int rc= 0;
533
  if (strncmp(name, "#mysql50#", 9))
534
    return 1;
535
  sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9);
206.3.1 by Patrick Galbraith
Most everything working with client rename
536
  if (drizzle_query(sock, qbuf))
1 by brian
clean slate
537
  {
538
    fprintf(stderr, "Failed to %s\n", qbuf);
206.3.1 by Patrick Galbraith
Most everything working with client rename
539
    fprintf(stderr, "Error: %s\n", drizzle_error(sock));
1 by brian
clean slate
540
    rc= 1;
541
  }
542
  if (verbose)
543
    printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
544
  return rc;
545
}
546
547
static int fix_database_storage_name(const char *name)
548
{
549
  char qbuf[100 + NAME_LEN*4];
550
  int rc= 0;
551
  if (strncmp(name, "#mysql50#", 9))
552
    return 1;
553
  sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name);
206.3.1 by Patrick Galbraith
Most everything working with client rename
554
  if (drizzle_query(sock, qbuf))
1 by brian
clean slate
555
  {
556
    fprintf(stderr, "Failed to %s\n", qbuf);
206.3.1 by Patrick Galbraith
Most everything working with client rename
557
    fprintf(stderr, "Error: %s\n", drizzle_error(sock));
1 by brian
clean slate
558
    rc= 1;
559
  }
560
  if (verbose)
561
    printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
562
  return rc;
563
}
564
565
static int process_one_db(char *database)
566
{
567
  if (what_to_do == DO_UPGRADE)
568
  {
569
    int rc= 0;
570
    if (opt_fix_db_names && !strncmp(database,"#mysql50#", 9))
571
    {
572
      rc= fix_database_storage_name(database);
573
      database+= 9;
574
    }
575
    if (rc || !opt_fix_table_names)
576
      return rc;
577
  }
578
  return process_all_tables_in_db(database);
579
}
580
581
582
static int use_db(char *database)
583
{
206.3.1 by Patrick Galbraith
Most everything working with client rename
584
  if (drizzle_get_server_version(sock) >= 50003 &&
1 by brian
clean slate
585
      !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
586
    return 1;
206.3.1 by Patrick Galbraith
Most everything working with client rename
587
  if (drizzle_select_db(sock, database))
1 by brian
clean slate
588
  {
589
    DBerror(sock, "when selecting the database");
590
    return 1;
591
  }
592
  return 0;
593
} /* use_db */
594
595
596
static int handle_request_for_tables(char *tables, uint length)
597
{
598
  char *query, *end, options[100], message[100];
599
  uint query_length= 0;
600
  const char *op = 0;
601
602
  options[0] = 0;
603
  end = options;
604
  switch (what_to_do) {
605
  case DO_CHECK:
606
    op = "CHECK";
607
    if (opt_quick)              end = strmov(end, " QUICK");
608
    if (opt_fast)               end = strmov(end, " FAST");
609
    if (opt_medium_check)       end = strmov(end, " MEDIUM"); /* Default */
610
    if (opt_extended)           end = strmov(end, " EXTENDED");
611
    if (opt_check_only_changed) end = strmov(end, " CHANGED");
612
    if (opt_upgrade)            end = strmov(end, " FOR UPGRADE");
613
    break;
614
  case DO_REPAIR:
615
    op= (opt_write_binlog) ? "REPAIR" : "REPAIR NO_WRITE_TO_BINLOG";
616
    if (opt_quick)              end = strmov(end, " QUICK");
617
    if (opt_extended)           end = strmov(end, " EXTENDED");
618
    if (opt_frm)                end = strmov(end, " USE_FRM");
619
    break;
620
  case DO_ANALYZE:
621
    op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
622
    break;
623
  case DO_OPTIMIZE:
624
    op= (opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG";
625
    break;
626
  case DO_UPGRADE:
627
    return fix_table_storage_name(tables);
628
  }
629
630
  if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME))))
631
    return 1;
632
  if (opt_all_in_1)
633
  {
634
    /* No backticks here as we added them before */
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
635
    query_length= sprintf(query, "%s TABLE %s %s", op, tables, options);
1 by brian
clean slate
636
  }
637
  else
638
  {
639
    char *ptr;
640
641
    ptr= strmov(strmov(query, op), " TABLE ");
642
    ptr= fix_table_name(ptr, tables);
643
    ptr= strxmov(ptr, " ", options, NullS);
644
    query_length= (uint) (ptr - query);
645
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
646
  if (drizzle_real_query(sock, query, query_length))
1 by brian
clean slate
647
  {
648
    sprintf(message, "when executing '%s TABLE ... %s'", op, options);
649
    DBerror(sock, message);
650
    return 1;
651
  }
652
  print_result();
653
  my_free(query, MYF(0));
654
  return 0;
655
}
656
657
658
static void print_result()
659
{
206.3.1 by Patrick Galbraith
Most everything working with client rename
660
  DRIZZLE_RES *res;
661
  DRIZZLE_ROW row;
1 by brian
clean slate
662
  char prev[NAME_LEN*2+2];
663
  uint i;
143 by Brian Aker
Bool cleanup.
664
  bool found_error=0;
1 by brian
clean slate
665
206.3.1 by Patrick Galbraith
Most everything working with client rename
666
  res = drizzle_use_result(sock);
1 by brian
clean slate
667
668
  prev[0] = '\0';
206.3.1 by Patrick Galbraith
Most everything working with client rename
669
  for (i = 0; (row = drizzle_fetch_row(res)); i++)
1 by brian
clean slate
670
  {
671
    int changed = strcmp(prev, row[0]);
143 by Brian Aker
Bool cleanup.
672
    bool status = !strcmp(row[2], "status");
1 by brian
clean slate
673
674
    if (status)
675
    {
676
      /*
677
        if there was an error with the table, we have --auto-repair set,
678
        and this isn't a repair op, then add the table to the tables4repair
679
        list
680
      */
681
      if (found_error && opt_auto_repair && what_to_do != DO_REPAIR &&
206.3.1 by Patrick Galbraith
Most everything working with client rename
682
    strcmp(row[3],"OK"))
683
  insert_dynamic(&tables4repair, (uchar*) prev);
1 by brian
clean slate
684
      found_error=0;
685
      if (opt_silent)
206.3.1 by Patrick Galbraith
Most everything working with client rename
686
  continue;
1 by brian
clean slate
687
    }
688
    if (status && changed)
689
      printf("%-50s %s", row[0], row[3]);
690
    else if (!status && changed)
691
    {
692
      printf("%s\n%-9s: %s", row[0], row[2], row[3]);
693
      if (strcmp(row[2],"note"))
206.3.1 by Patrick Galbraith
Most everything working with client rename
694
  found_error=1;
1 by brian
clean slate
695
    }
696
    else
697
      printf("%-9s: %s", row[2], row[3]);
698
    strmov(prev, row[0]);
699
    putchar('\n');
700
  }
701
  /* add the last table to be repaired to the list */
702
  if (found_error && opt_auto_repair && what_to_do != DO_REPAIR)
703
    insert_dynamic(&tables4repair, (uchar*) prev);
206.3.1 by Patrick Galbraith
Most everything working with client rename
704
  drizzle_free_result(res);
1 by brian
clean slate
705
}
706
707
708
static int dbConnect(char *host, char *user, char *passwd)
709
{
142.1.2 by Patrick
All DBUG_x removed from client/
710
1 by brian
clean slate
711
  if (verbose)
712
  {
713
    fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
714
  }
202.2.4 by Monty Taylor
Merged from Patrick.
715
  drizzle_create(&drizzle_connection);
1 by brian
clean slate
716
  if (opt_compress)
206.3.1 by Patrick Galbraith
Most everything working with client rename
717
    drizzle_options(&drizzle_connection, DRIZZLE_OPT_COMPRESS, NullS);
1 by brian
clean slate
718
  if (opt_protocol)
206.3.1 by Patrick Galbraith
Most everything working with client rename
719
    drizzle_options(&drizzle_connection,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
720
  if (!(sock = drizzle_connect(&drizzle_connection, host, user, passwd,
1 by brian
clean slate
721
         NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
722
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
723
    DBerror(&drizzle_connection, "when trying to connect");
1 by brian
clean slate
724
    return 1;
725
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
726
  drizzle_connection.reconnect= 1;
1 by brian
clean slate
727
  return 0;
728
} /* dbConnect */
729
730
731
static void dbDisconnect(char *host)
732
{
733
  if (verbose)
734
    fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
206.3.1 by Patrick Galbraith
Most everything working with client rename
735
  drizzle_close(sock);
1 by brian
clean slate
736
} /* dbDisconnect */
737
738
206.3.1 by Patrick Galbraith
Most everything working with client rename
739
static void DBerror(DRIZZLE *drizzle, const char *when)
1 by brian
clean slate
740
{
741
  my_printf_error(0,"Got error: %d: %s %s", MYF(0),
206.3.1 by Patrick Galbraith
Most everything working with client rename
742
      drizzle_errno(drizzle), drizzle_error(drizzle), when);
1 by brian
clean slate
743
  safe_exit(EX_MYSQLERR);
142.1.2 by Patrick
All DBUG_x removed from client/
744
  return;
1 by brian
clean slate
745
} /* DBerror */
746
747
748
static void safe_exit(int error)
749
{
750
  if (!first_error)
751
    first_error= error;
752
  if (ignore_errors)
753
    return;
754
  if (sock)
206.3.1 by Patrick Galbraith
Most everything working with client rename
755
    drizzle_close(sock);
1 by brian
clean slate
756
  exit(error);
757
}
758
759
760
int main(int argc, char **argv)
761
{
762
  MY_INIT(argv[0]);
763
  /*
764
  ** Check out the args
765
  */
766
  if (get_options(&argc, &argv))
767
  {
768
    my_end(my_end_arg);
769
    exit(EX_USAGE);
770
  }
771
  if (dbConnect(current_host, current_user, opt_password))
772
    exit(EX_MYSQLERR);
773
774
  if (opt_auto_repair &&
775
      my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64))
776
  {
777
    first_error = 1;
778
    goto end;
779
  }
780
781
  if (opt_alldbs)
782
    process_all_databases();
783
  /* Only one database and selected table(s) */
784
  else if (argc > 1 && !opt_databases)
785
    process_selected_tables(*argv, (argv + 1), (argc - 1));
786
  /* One or more databases, all tables */
787
  else
788
    process_databases(argv);
789
  if (opt_auto_repair)
790
  {
791
    uint i;
792
793
    if (!opt_silent && tables4repair.elements)
794
      puts("\nRepairing tables");
795
    what_to_do = DO_REPAIR;
796
    for (i = 0; i < tables4repair.elements ; i++)
797
    {
798
      char *name= (char*) dynamic_array_ptr(&tables4repair, i);
799
      handle_request_for_tables(name, fixed_name_length(name));
800
    }
801
  }
802
 end:
803
  dbDisconnect(current_host);
804
  if (opt_auto_repair)
805
    delete_dynamic(&tables4repair);
806
  my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
807
  my_end(my_end_arg);
808
  return(first_error!=0);
809
} /* main */