~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzlecheck.cc

  • Committer: Monty Taylor
  • Date: 2010-12-24 02:13:05 UTC
  • mto: This revision was merged to the branch mainline in revision 2038.
  • Revision ID: mordred@inaugust.com-20101224021305-e3slv1cyjczqorij
Changed the bzrignore file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2008 Drizzle development team
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
 
 
16
 
/* By Jani Tolonen, 2001-04-20, MySQL, MYSQL Development Team */
17
 
 
18
 
#define CHECK_VERSION "2.5.0"
19
 
 
20
 
#include "client_priv.h"
21
 
#include <vector>
22
 
#include <string>
23
 
#include <mystrings/m_ctype.h>
24
 
 
25
 
template class std::vector<std::string>;
26
 
 
27
 
using namespace std;
28
 
/* Exit codes */
29
 
 
30
 
#define EX_USAGE 1
31
 
#define EX_MYSQLERR 2
32
 
 
33
 
static DRIZZLE drizzle_connection, *sock = 0;
34
 
static bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
35
 
               opt_compress = 0, opt_databases = 0, opt_fast = 0,
36
 
               opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
37
 
               opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
38
 
               tty_password= 0, opt_frm= 0, debug_info_flag= 0, debug_check_flag= 0,
39
 
               opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0,
40
 
               opt_write_binlog= 1;
41
 
static uint verbose = 0, opt_mysql_port=0;
42
 
static int my_end_arg;
43
 
static char * opt_mysql_unix_port = 0;
44
 
static char *opt_password = 0, *current_user = 0,
45
 
      *default_charset = (char *)DRIZZLE_DEFAULT_CHARSET_NAME,
46
 
      *current_host = 0;
47
 
static int first_error = 0;
48
 
vector<string> tables4repair;
49
 
static uint opt_protocol=0;
50
 
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
51
 
 
52
 
enum operations { DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
53
 
 
54
 
static struct my_option my_long_options[] =
55
 
{
56
 
  {"all-databases", 'A',
57
 
   "Check all the databases. This will be same as  --databases with all databases selected.",
58
 
   (char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
59
 
   0, 0},
60
 
  {"analyze", 'a', "Analyze given tables.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
61
 
   0, 0, 0, 0},
62
 
  {"all-in-1", '1',
63
 
   "Instead of issuing one query for each table, use one query per database, naming all tables in the database in a comma-separated list.",
64
 
   (char**) &opt_all_in_1, (char**) &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0,
65
 
   0, 0, 0},
66
 
  {"auto-repair", OPT_AUTO_REPAIR,
67
 
   "If a checked table is corrupted, automatically fix it. Repairing will be done after all tables have been checked, if corrupted ones were found.",
68
 
   (char**) &opt_auto_repair, (char**) &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0,
69
 
   0, 0, 0, 0, 0},
70
 
  {"character-sets-dir", OPT_CHARSETS_DIR,
71
 
   "Directory where character sets are.", (char**) &charsets_dir,
72
 
   (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
73
 
  {"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
74
 
   0, 0, 0, 0},
75
 
  {"check-only-changed", 'C',
76
 
   "Check only tables that have changed since last check or haven't been closed properly.",
77
 
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
78
 
  {"check-upgrade", 'g',
79
 
   "Check tables for version-dependent changes. May be used with --auto-repair to correct tables requiring version-dependent updates.",
80
 
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
81
 
  {"compress", OPT_COMPRESS, "Use compression in server/client protocol.",
82
 
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
83
 
   0, 0, 0},
84
 
  {"databases", 'B',
85
 
   "To check several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames.",
86
 
   (char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG,
87
 
   0, 0, 0, 0, 0, 0},
88
 
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
89
 
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
90
 
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
91
 
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
92
 
   (char**) &debug_info_flag, (char**) &debug_info_flag,
93
 
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
94
 
  {"default-character-set", OPT_DEFAULT_CHARSET,
95
 
   "Set the default character set.", (char**) &default_charset,
96
 
   (char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
97
 
  {"fast",'F', "Check only tables that haven't been closed properly.",
98
 
   (char**) &opt_fast, (char**) &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
99
 
   0},
100
 
  {"fix-db-names", OPT_FIX_DB_NAMES, "Fix database names.",
101
 
    (char**) &opt_fix_db_names, (char**) &opt_fix_db_names,
102
 
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
103
 
  {"fix-table-names", OPT_FIX_TABLE_NAMES, "Fix table names.",
104
 
    (char**) &opt_fix_table_names, (char**) &opt_fix_table_names,
105
 
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
106
 
  {"force", 'f', "Continue even if we get an sql-error.",
107
 
   (char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
108
 
   0, 0, 0, 0},
109
 
  {"extended", 'e',
110
 
   "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.",
111
 
   (char**) &opt_extended, (char**) &opt_extended, 0, GET_BOOL, NO_ARG, 0, 0, 0,
112
 
   0, 0, 0},
113
 
  {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
114
 
   NO_ARG, 0, 0, 0, 0, 0, 0},
115
 
  {"host",'h', "Connect to host.", (char**) &current_host,
116
 
   (char**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
117
 
  {"medium-check", 'm',
118
 
   "Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.",
119
 
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
120
 
  {"write-binlog", OPT_WRITE_BINLOG,
121
 
   "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Use --skip-write-binlog when commands should not be sent to replication slaves.",
122
 
   (char**) &opt_write_binlog, (char**) &opt_write_binlog, 0, GET_BOOL, NO_ARG,
123
 
   1, 0, 0, 0, 0, 0},
124
 
  {"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
125
 
   0, 0},
126
 
  {"password", 'p',
127
 
   "Password to use when connecting to server. If password is not given it's solicited on the tty.",
128
 
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
129
 
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
130
 
   "order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
131
 
   "built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
132
 
   (char**) &opt_mysql_port,
133
 
   (char**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
134
 
   0},
135
 
  {"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
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.",
139
 
   (char**) &opt_quick, (char**) &opt_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
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},
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},
146
 
  {"socket", 'S', "Socket file to use for connection.",
147
 
   (char**) &opt_mysql_unix_port, (char**) &opt_mysql_unix_port, 0, GET_STR,
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.",
153
 
   (char**) &opt_frm, (char**) &opt_frm, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
154
 
   0},
155
 
#ifndef DONT_ALLOW_USER_CHANGE
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},
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);
172
 
static int process_all_databases(void);
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(const char *tables, uint length);
179
 
static int dbConnect(char *host, char *user,char *passwd);
180
 
static void dbDisconnect(char *host);
181
 
static void DBerror(DRIZZLE *drizzle, const char *when);
182
 
static void safe_exit(int error);
183
 
static void print_result(void);
184
 
static uint fixed_name_length(const char *name);
185
 
static char *fix_table_name(char *dest, const 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
 
   drizzle_get_client_info(), 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.");
203
 
  puts("Please consult the Drizzle manual for latest information about the");
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",
214
 
   my_progname);
215
 
  printf("OR     %s [OPTIONS] --all-databases\n", my_progname);
216
 
  print_defaults("drizzle", load_default_groups);
217
 
  my_print_help(my_long_options);
218
 
  my_print_variables(my_long_options);
219
 
} /* usage */
220
 
 
221
 
static bool
222
 
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
223
 
         char *argument)
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
 
      free(opt_password);
261
 
      opt_password = my_strdup(argument, MYF(MY_FAE));
262
 
      while (*argument) *argument++= 'x';    /* Destroy argument */
263
 
      if (*start)
264
 
  start[1] = 0;                             /* Cut length of argument */
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);
284
 
  case OPT_DRIZZLE_PROTOCOL:
285
 
    break;
286
 
  }
287
 
  return 0;
288
 
}
289
 
 
290
 
 
291
 
static int get_options(int *argc, char ***argv)
292
 
{
293
 
  int ho_error;
294
 
 
295
 
  if (*argc == 1)
296
 
  {
297
 
    usage();
298
 
    exit(0);
299
 
  }
300
 
 
301
 
  load_defaults("drizzle", load_default_groups, argc, argv);
302
 
 
303
 
  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
304
 
    exit(ho_error);
305
 
 
306
 
  if (!what_to_do)
307
 
  {
308
 
    int pnlen = strlen(my_progname);
309
 
 
310
 
    if (pnlen < 6) /* name too short */
311
 
      what_to_do = DO_CHECK;
312
 
    else if (!strcmp("repair", my_progname + pnlen - 6))
313
 
      what_to_do = DO_REPAIR;
314
 
    else if (!strcmp("analyze", my_progname + pnlen - 7))
315
 
      what_to_do = DO_ANALYZE;
316
 
    else if  (!strcmp("optimize", my_progname + pnlen - 8))
317
 
      what_to_do = DO_OPTIMIZE;
318
 
    else
319
 
      what_to_do = DO_CHECK;
320
 
  }
321
 
 
322
 
  /* TODO: This variable is not yet used */
323
 
  if (strcmp(default_charset, charset_info->csname) &&
324
 
      !(charset_info= get_charset_by_csname(default_charset,
325
 
                MY_CS_PRIMARY, MYF(MY_WME))))
326
 
      exit(1);
327
 
  if (*argc > 0 && opt_alldbs)
328
 
  {
329
 
    printf("You should give only options, no arguments at all, with option\n");
330
 
    printf("--all-databases. Please see %s --help for more information.\n",
331
 
     my_progname);
332
 
    return 1;
333
 
  }
334
 
  if (*argc < 1 && !opt_alldbs)
335
 
  {
336
 
    printf("You forgot to give the arguments! Please see %s --help\n",
337
 
     my_progname);
338
 
    printf("for more information.\n");
339
 
    return 1;
340
 
  }
341
 
  if (tty_password)
342
 
    opt_password = get_tty_password(NULL);
343
 
  if (debug_info_flag)
344
 
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
345
 
  if (debug_check_flag)
346
 
    my_end_arg= MY_CHECK_ERROR;
347
 
  return(0);
348
 
} /* get_options */
349
 
 
350
 
 
351
 
static int process_all_databases()
352
 
{
353
 
  DRIZZLE_ROW row;
354
 
  DRIZZLE_RES *tableres;
355
 
  int result = 0;
356
 
 
357
 
  if (drizzle_query(sock, "SHOW DATABASES") ||
358
 
      !(tableres = drizzle_store_result(sock)))
359
 
  {
360
 
    my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
361
 
        MYF(0), drizzle_error(sock));
362
 
    return 1;
363
 
  }
364
 
  while ((row = drizzle_fetch_row(tableres)))
365
 
  {
366
 
    if (process_one_db(row[0]))
367
 
      result = 1;
368
 
  }
369
 
  return result;
370
 
}
371
 
/* process_all_databases */
372
 
 
373
 
 
374
 
static int process_databases(char **db_names)
375
 
{
376
 
  int result = 0;
377
 
  for ( ; *db_names ; db_names++)
378
 
  {
379
 
    if (process_one_db(*db_names))
380
 
      result = 1;
381
 
  }
382
 
  return result;
383
 
} /* process_databases */
384
 
 
385
 
 
386
 
static int process_selected_tables(char *db, char **table_names, int tables)
387
 
{
388
 
  if (use_db(db))
389
 
    return 1;
390
 
  if (opt_all_in_1)
391
 
  {
392
 
    /*
393
 
      We need table list in form `a`, `b`, `c`
394
 
      that's why we need 2 more chars added to to each table name
395
 
      space is for more readable output in logs and in case of error
396
 
    */   
397
 
    char *table_names_comma_sep, *end;
398
 
    int i, tot_length = 0;
399
 
 
400
 
    for (i = 0; i < tables; i++)
401
 
      tot_length+= fixed_name_length(*(table_names + i)) + 2;
402
 
 
403
 
    if (!(table_names_comma_sep = (char *)
404
 
    my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
405
 
      return 1;
406
 
 
407
 
    for (end = table_names_comma_sep + 1; tables > 0;
408
 
   tables--, table_names++)
409
 
    {
410
 
      end= fix_table_name(end, *table_names);
411
 
      *end++= ',';
412
 
    }
413
 
    *--end = 0;
414
 
    handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1);
415
 
    free(table_names_comma_sep);
416
 
  }
417
 
  else
418
 
    for (; tables > 0; tables--, table_names++)
419
 
      handle_request_for_tables(*table_names, fixed_name_length(*table_names));
420
 
  return 0;
421
 
} /* process_selected_tables */
422
 
 
423
 
 
424
 
static uint fixed_name_length(const char *name)
425
 
{
426
 
  const char *p;
427
 
  uint extra_length= 2;  /* count the first/last backticks */
428
 
 
429
 
  for (p= name; *p; p++)
430
 
  {
431
 
    if (*p == '`')
432
 
      extra_length++;
433
 
    else if (*p == '.')
434
 
      extra_length+= 2;
435
 
  }
436
 
  return (p - name) + extra_length;
437
 
}
438
 
 
439
 
 
440
 
static char *fix_table_name(char *dest, const char *src)
441
 
{
442
 
  *dest++= '`';
443
 
  for (; *src; src++)
444
 
  {
445
 
    switch (*src) {
446
 
    case '.':            /* add backticks around '.' */
447
 
      *dest++= '`';
448
 
      *dest++= '.';
449
 
      *dest++= '`';
450
 
      break;
451
 
    case '`':            /* escape backtick character */
452
 
      *dest++= '`';
453
 
      /* fall through */
454
 
    default:
455
 
      *dest++= *src;
456
 
    }
457
 
  }
458
 
  *dest++= '`';
459
 
  return dest;
460
 
}
461
 
 
462
 
 
463
 
static int process_all_tables_in_db(char *database)
464
 
{
465
 
  DRIZZLE_RES *res;
466
 
  DRIZZLE_ROW row;
467
 
  uint num_columns;
468
 
 
469
 
  if (use_db(database))
470
 
    return 1;
471
 
  if (drizzle_query(sock, "SHOW /*!50002 FULL*/ TABLES") ||
472
 
  !((res= drizzle_store_result(sock))))
473
 
    return 1;
474
 
 
475
 
  num_columns= drizzle_num_fields(res);
476
 
 
477
 
  if (opt_all_in_1)
478
 
  {
479
 
    /*
480
 
      We need table list in form `a`, `b`, `c`
481
 
      that's why we need 2 more chars added to to each table name
482
 
      space is for more readable output in logs and in case of error
483
 
     */
484
 
 
485
 
    char *tables, *end;
486
 
    uint tot_length = 0;
487
 
 
488
 
    while ((row = drizzle_fetch_row(res)))
489
 
      tot_length+= fixed_name_length(row[0]) + 2;
490
 
    drizzle_data_seek(res, 0);
491
 
 
492
 
    if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
493
 
    {
494
 
      drizzle_free_result(res);
495
 
      return 1;
496
 
    }
497
 
    for (end = tables + 1; (row = drizzle_fetch_row(res)) ;)
498
 
    {
499
 
      if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
500
 
        continue;
501
 
 
502
 
      end= fix_table_name(end, row[0]);
503
 
      *end++= ',';
504
 
    }
505
 
    *--end = 0;
506
 
    if (tot_length)
507
 
      handle_request_for_tables(tables + 1, tot_length - 1);
508
 
    free(tables);
509
 
  }
510
 
  else
511
 
  {
512
 
    while ((row = drizzle_fetch_row(res)))
513
 
    {
514
 
      /* Skip views if we don't perform renaming. */
515
 
      if ((what_to_do != DO_UPGRADE) && (num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
516
 
        continue;
517
 
 
518
 
      handle_request_for_tables(row[0], fixed_name_length(row[0]));
519
 
    }
520
 
  }
521
 
  drizzle_free_result(res);
522
 
  return 0;
523
 
} /* process_all_tables_in_db */
524
 
 
525
 
 
526
 
 
527
 
static int fix_table_storage_name(const char *name)
528
 
{
529
 
  char qbuf[100 + NAME_LEN*4];
530
 
  int rc= 0;
531
 
  if (strncmp(name, "#mysql50#", 9))
532
 
    return 1;
533
 
  sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9);
534
 
  if (drizzle_query(sock, qbuf))
535
 
  {
536
 
    fprintf(stderr, "Failed to %s\n", qbuf);
537
 
    fprintf(stderr, "Error: %s\n", drizzle_error(sock));
538
 
    rc= 1;
539
 
  }
540
 
  if (verbose)
541
 
    printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
542
 
  return rc;
543
 
}
544
 
 
545
 
static int fix_database_storage_name(const char *name)
546
 
{
547
 
  char qbuf[100 + NAME_LEN*4];
548
 
  int rc= 0;
549
 
  if (strncmp(name, "#mysql50#", 9))
550
 
    return 1;
551
 
  sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name);
552
 
  if (drizzle_query(sock, qbuf))
553
 
  {
554
 
    fprintf(stderr, "Failed to %s\n", qbuf);
555
 
    fprintf(stderr, "Error: %s\n", drizzle_error(sock));
556
 
    rc= 1;
557
 
  }
558
 
  if (verbose)
559
 
    printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
560
 
  return rc;
561
 
}
562
 
 
563
 
static int process_one_db(char *database)
564
 
{
565
 
  if (what_to_do == DO_UPGRADE)
566
 
  {
567
 
    int rc= 0;
568
 
    if (opt_fix_db_names && !strncmp(database,"#mysql50#", 9))
569
 
    {
570
 
      rc= fix_database_storage_name(database);
571
 
      database+= 9;
572
 
    }
573
 
    if (rc || !opt_fix_table_names)
574
 
      return rc;
575
 
  }
576
 
  return process_all_tables_in_db(database);
577
 
}
578
 
 
579
 
 
580
 
static int use_db(char *database)
581
 
{
582
 
  if (drizzle_get_server_version(sock) >= 50003 &&
583
 
      !my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
584
 
    return 1;
585
 
  if (drizzle_select_db(sock, database))
586
 
  {
587
 
    DBerror(sock, "when selecting the database");
588
 
    return 1;
589
 
  }
590
 
  return 0;
591
 
} /* use_db */
592
 
 
593
 
 
594
 
static int handle_request_for_tables(const char *tables, uint length)
595
 
{
596
 
  char *query, *end, options[100], message[100];
597
 
  uint query_length= 0;
598
 
  const char *op = 0;
599
 
 
600
 
  options[0] = 0;
601
 
  end = options;
602
 
  switch (what_to_do) {
603
 
  case DO_CHECK:
604
 
    op = "CHECK";
605
 
    if (opt_quick)              end = my_stpcpy(end, " QUICK");
606
 
    if (opt_fast)               end = my_stpcpy(end, " FAST");
607
 
    if (opt_medium_check)       end = my_stpcpy(end, " MEDIUM"); /* Default */
608
 
    if (opt_extended)           end = my_stpcpy(end, " EXTENDED");
609
 
    if (opt_check_only_changed) end = my_stpcpy(end, " CHANGED");
610
 
    if (opt_upgrade)            end = my_stpcpy(end, " FOR UPGRADE");
611
 
    break;
612
 
  case DO_REPAIR:
613
 
    op= (opt_write_binlog) ? "REPAIR" : "REPAIR NO_WRITE_TO_BINLOG";
614
 
    if (opt_quick)              end = my_stpcpy(end, " QUICK");
615
 
    if (opt_extended)           end = my_stpcpy(end, " EXTENDED");
616
 
    if (opt_frm)                end = my_stpcpy(end, " USE_FRM");
617
 
    break;
618
 
  case DO_ANALYZE:
619
 
    op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
620
 
    break;
621
 
  case DO_OPTIMIZE:
622
 
    op= (opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG";
623
 
    break;
624
 
  case DO_UPGRADE:
625
 
    return fix_table_storage_name(tables);
626
 
  }
627
 
 
628
 
  if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME))))
629
 
    return 1;
630
 
  if (opt_all_in_1)
631
 
  {
632
 
    /* No backticks here as we added them before */
633
 
    query_length= sprintf(query, "%s TABLE %s %s", op, tables, options);
634
 
  }
635
 
  else
636
 
  {
637
 
    char *ptr;
638
 
 
639
 
    ptr= my_stpcpy(my_stpcpy(query, op), " TABLE ");
640
 
    ptr= fix_table_name(ptr, tables);
641
 
    ptr= strxmov(ptr, " ", options, NULL);
642
 
    query_length= (uint) (ptr - query);
643
 
  }
644
 
  if (drizzle_real_query(sock, query, query_length))
645
 
  {
646
 
    sprintf(message, "when executing '%s TABLE ... %s'", op, options);
647
 
    DBerror(sock, message);
648
 
    return 1;
649
 
  }
650
 
  print_result();
651
 
  free(query);
652
 
  return 0;
653
 
}
654
 
 
655
 
 
656
 
static void print_result()
657
 
{
658
 
  DRIZZLE_RES *res;
659
 
  DRIZZLE_ROW row;
660
 
  char prev[NAME_LEN*2+2];
661
 
  uint i;
662
 
  bool found_error=0;
663
 
 
664
 
  res = drizzle_use_result(sock);
665
 
 
666
 
  prev[0] = '\0';
667
 
  for (i = 0; (row = drizzle_fetch_row(res)); i++)
668
 
  {
669
 
    int changed = strcmp(prev, row[0]);
670
 
    bool status = !strcmp(row[2], "status");
671
 
 
672
 
    if (status)
673
 
    {
674
 
      /*
675
 
        if there was an error with the table, we have --auto-repair set,
676
 
        and this isn't a repair op, then add the table to the tables4repair
677
 
        list
678
 
      */
679
 
      if (found_error && opt_auto_repair && what_to_do != DO_REPAIR &&
680
 
          strcmp(row[3],"OK"))
681
 
        tables4repair.push_back(string(prev));
682
 
      found_error=0;
683
 
      if (opt_silent)
684
 
  continue;
685
 
    }
686
 
    if (status && changed)
687
 
      printf("%-50s %s", row[0], row[3]);
688
 
    else if (!status && changed)
689
 
    {
690
 
      printf("%s\n%-9s: %s", row[0], row[2], row[3]);
691
 
      if (strcmp(row[2],"note"))
692
 
  found_error=1;
693
 
    }
694
 
    else
695
 
      printf("%-9s: %s", row[2], row[3]);
696
 
    my_stpcpy(prev, row[0]);
697
 
    putchar('\n');
698
 
  }
699
 
  /* add the last table to be repaired to the list */
700
 
  if (found_error && opt_auto_repair && what_to_do != DO_REPAIR)
701
 
    tables4repair.push_back(string(prev));
702
 
  drizzle_free_result(res);
703
 
}
704
 
 
705
 
 
706
 
static int dbConnect(char *host, char *user, char *passwd)
707
 
{
708
 
 
709
 
  if (verbose)
710
 
  {
711
 
    fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
712
 
  }
713
 
  drizzle_create(&drizzle_connection);
714
 
  if (opt_compress)
715
 
    drizzle_options(&drizzle_connection, DRIZZLE_OPT_COMPRESS, NULL);
716
 
  if (opt_protocol)
717
 
    drizzle_options(&drizzle_connection,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
718
 
  if (!(sock = drizzle_connect(&drizzle_connection, host, user, passwd,
719
 
         NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
720
 
  {
721
 
    DBerror(&drizzle_connection, "when trying to connect");
722
 
    return 1;
723
 
  }
724
 
  drizzle_connection.reconnect= 1;
725
 
  return 0;
726
 
} /* dbConnect */
727
 
 
728
 
 
729
 
static void dbDisconnect(char *host)
730
 
{
731
 
  if (verbose)
732
 
    fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
733
 
  drizzle_close(sock);
734
 
} /* dbDisconnect */
735
 
 
736
 
 
737
 
static void DBerror(DRIZZLE *drizzle, const char *when)
738
 
{
739
 
  my_printf_error(0,"Got error: %d: %s %s", MYF(0),
740
 
      drizzle_errno(drizzle), drizzle_error(drizzle), when);
741
 
  safe_exit(EX_MYSQLERR);
742
 
  return;
743
 
} /* DBerror */
744
 
 
745
 
 
746
 
static void safe_exit(int error)
747
 
{
748
 
  if (!first_error)
749
 
    first_error= error;
750
 
  if (ignore_errors)
751
 
    return;
752
 
  if (sock)
753
 
    drizzle_close(sock);
754
 
  exit(error);
755
 
}
756
 
 
757
 
 
758
 
int main(int argc, char **argv)
759
 
{
760
 
  MY_INIT(argv[0]);
761
 
  /*
762
 
  ** Check out the args
763
 
  */
764
 
  if (get_options(&argc, &argv))
765
 
  {
766
 
    my_end(my_end_arg);
767
 
    exit(EX_USAGE);
768
 
  }
769
 
  if (dbConnect(current_host, current_user, opt_password))
770
 
    exit(EX_MYSQLERR);
771
 
 
772
 
  if (opt_auto_repair)
773
 
  {
774
 
    tables4repair.reserve(64);
775
 
    if (tables4repair.capacity() == 0)
776
 
    {
777
 
      first_error = 1;
778
 
      goto end;
779
 
    }
780
 
  }
781
 
 
782
 
 
783
 
  if (opt_alldbs)
784
 
    process_all_databases();
785
 
  /* Only one database and selected table(s) */
786
 
  else if (argc > 1 && !opt_databases)
787
 
    process_selected_tables(*argv, (argv + 1), (argc - 1));
788
 
  /* One or more databases, all tables */
789
 
  else
790
 
    process_databases(argv);
791
 
  if (opt_auto_repair)
792
 
  {
793
 
 
794
 
    if (!opt_silent && (tables4repair.size() > 0))
795
 
      puts("\nRepairing tables");
796
 
    what_to_do = DO_REPAIR;
797
 
    vector<string>::iterator i;
798
 
    for ( i= tables4repair.begin() ; i < tables4repair.end() ; i++)
799
 
    {
800
 
      const char *name= (*i).c_str();
801
 
      handle_request_for_tables(name, fixed_name_length(name));
802
 
    }
803
 
  }
804
 
 end:
805
 
  dbDisconnect(current_host);
806
 
  free(opt_password);
807
 
  my_end(my_end_arg);
808
 
  return(first_error!=0);
809
 
} /* main */