~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzlecheck.cc

  • Committer: Brian Aker
  • Date: 2010-12-18 18:24:57 UTC
  • mfrom: (1999.6.3 trunk)
  • Revision ID: brian@tangent.org-20101218182457-yi1wd0so2hml1k1w
Merge in Lee's copyright header fix

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 <vector>
21
 
#include <string>
22
 
#include "client_priv.h"
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_latin1;
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, my.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("my", 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
 
      my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
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
 
    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) &&
326
 
      !(charset_info= get_charset_by_csname(default_charset,
327
 
                MY_CS_PRIMARY, MYF(MY_WME))))
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",
333
 
     my_progname);
334
 
    return 1;
335
 
  }
336
 
  if (*argc < 1 && !opt_alldbs)
337
 
  {
338
 
    printf("You forgot to give the arguments! Please see %s --help\n",
339
 
     my_progname);
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
 
{
355
 
  DRIZZLE_ROW row;
356
 
  DRIZZLE_RES *tableres;
357
 
  int result = 0;
358
 
 
359
 
  if (drizzle_query(sock, "SHOW DATABASES") ||
360
 
      !(tableres = drizzle_store_result(sock)))
361
 
  {
362
 
    my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
363
 
        MYF(0), drizzle_error(sock));
364
 
    return 1;
365
 
  }
366
 
  while ((row = drizzle_fetch_row(tableres)))
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
 
  {
394
 
    /*
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
398
 
    */   
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 *)
406
 
    my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
407
 
      return 1;
408
 
 
409
 
    for (end = table_names_comma_sep + 1; tables > 0;
410
 
   tables--, table_names++)
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 */
430
 
 
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, const 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
 
{
467
 
  DRIZZLE_RES *res;
468
 
  DRIZZLE_ROW row;
469
 
  uint num_columns;
470
 
 
471
 
  if (use_db(database))
472
 
    return 1;
473
 
  if (drizzle_query(sock, "SHOW /*!50002 FULL*/ TABLES") ||
474
 
  !((res= drizzle_store_result(sock))))
475
 
    return 1;
476
 
 
477
 
  num_columns= drizzle_num_fields(res);
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
 
 
490
 
    while ((row = drizzle_fetch_row(res)))
491
 
      tot_length+= fixed_name_length(row[0]) + 2;
492
 
    drizzle_data_seek(res, 0);
493
 
 
494
 
    if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
495
 
    {
496
 
      drizzle_free_result(res);
497
 
      return 1;
498
 
    }
499
 
    for (end = tables + 1; (row = drizzle_fetch_row(res)) ;)
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
 
  {
514
 
    while ((row = drizzle_fetch_row(res)))
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
 
  }
523
 
  drizzle_free_result(res);
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);
536
 
  if (drizzle_query(sock, qbuf))
537
 
  {
538
 
    fprintf(stderr, "Failed to %s\n", qbuf);
539
 
    fprintf(stderr, "Error: %s\n", drizzle_error(sock));
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);
554
 
  if (drizzle_query(sock, qbuf))
555
 
  {
556
 
    fprintf(stderr, "Failed to %s\n", qbuf);
557
 
    fprintf(stderr, "Error: %s\n", drizzle_error(sock));
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
 
{
584
 
  if (drizzle_get_server_version(sock) >= 50003 &&
585
 
      !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
586
 
    return 1;
587
 
  if (drizzle_select_db(sock, database))
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(const 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 = stpcpy(end, " QUICK");
608
 
    if (opt_fast)               end = stpcpy(end, " FAST");
609
 
    if (opt_medium_check)       end = stpcpy(end, " MEDIUM"); /* Default */
610
 
    if (opt_extended)           end = stpcpy(end, " EXTENDED");
611
 
    if (opt_check_only_changed) end = stpcpy(end, " CHANGED");
612
 
    if (opt_upgrade)            end = stpcpy(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 = stpcpy(end, " QUICK");
617
 
    if (opt_extended)           end = stpcpy(end, " EXTENDED");
618
 
    if (opt_frm)                end = stpcpy(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 */
635
 
    query_length= sprintf(query, "%s TABLE %s %s", op, tables, options);
636
 
  }
637
 
  else
638
 
  {
639
 
    char *ptr;
640
 
 
641
 
    ptr= stpcpy(stpcpy(query, op), " TABLE ");
642
 
    ptr= fix_table_name(ptr, tables);
643
 
    ptr= strxmov(ptr, " ", options, NullS);
644
 
    query_length= (uint) (ptr - query);
645
 
  }
646
 
  if (drizzle_real_query(sock, query, query_length))
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
 
{
660
 
  DRIZZLE_RES *res;
661
 
  DRIZZLE_ROW row;
662
 
  char prev[NAME_LEN*2+2];
663
 
  uint i;
664
 
  bool found_error=0;
665
 
 
666
 
  res = drizzle_use_result(sock);
667
 
 
668
 
  prev[0] = '\0';
669
 
  for (i = 0; (row = drizzle_fetch_row(res)); i++)
670
 
  {
671
 
    int changed = strcmp(prev, row[0]);
672
 
    bool status = !strcmp(row[2], "status");
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 &&
682
 
          strcmp(row[3],"OK"))
683
 
        tables4repair.push_back(string(prev));
684
 
      found_error=0;
685
 
      if (opt_silent)
686
 
  continue;
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"))
694
 
  found_error=1;
695
 
    }
696
 
    else
697
 
      printf("%-9s: %s", row[2], row[3]);
698
 
    stpcpy(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
 
    tables4repair.push_back(string(prev));
704
 
  drizzle_free_result(res);
705
 
}
706
 
 
707
 
 
708
 
static int dbConnect(char *host, char *user, char *passwd)
709
 
{
710
 
 
711
 
  if (verbose)
712
 
  {
713
 
    fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
714
 
  }
715
 
  drizzle_create(&drizzle_connection);
716
 
  if (opt_compress)
717
 
    drizzle_options(&drizzle_connection, DRIZZLE_OPT_COMPRESS, NullS);
718
 
  if (opt_protocol)
719
 
    drizzle_options(&drizzle_connection,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
720
 
  if (!(sock = drizzle_connect(&drizzle_connection, host, user, passwd,
721
 
         NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
722
 
  {
723
 
    DBerror(&drizzle_connection, "when trying to connect");
724
 
    return 1;
725
 
  }
726
 
  drizzle_connection.reconnect= 1;
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");
735
 
  drizzle_close(sock);
736
 
} /* dbDisconnect */
737
 
 
738
 
 
739
 
static void DBerror(DRIZZLE *drizzle, const char *when)
740
 
{
741
 
  my_printf_error(0,"Got error: %d: %s %s", MYF(0),
742
 
      drizzle_errno(drizzle), drizzle_error(drizzle), when);
743
 
  safe_exit(EX_MYSQLERR);
744
 
  return;
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)
755
 
    drizzle_close(sock);
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
 
  {
776
 
    tables4repair.reserve(64);
777
 
    if (tables4repair.capacity() == 0)
778
 
    {
779
 
      first_error = 1;
780
 
      goto end;
781
 
    }
782
 
  }
783
 
 
784
 
 
785
 
  if (opt_alldbs)
786
 
    process_all_databases();
787
 
  /* Only one database and selected table(s) */
788
 
  else if (argc > 1 && !opt_databases)
789
 
    process_selected_tables(*argv, (argv + 1), (argc - 1));
790
 
  /* One or more databases, all tables */
791
 
  else
792
 
    process_databases(argv);
793
 
  if (opt_auto_repair)
794
 
  {
795
 
 
796
 
    if (!opt_silent && (tables4repair.size() > 0))
797
 
      puts("\nRepairing tables");
798
 
    what_to_do = DO_REPAIR;
799
 
    vector<string>::iterator i;
800
 
    for ( i= tables4repair.begin() ; i < tables4repair.end() ; i++)
801
 
    {
802
 
      const char *name= (*i).c_str();
803
 
      handle_request_for_tables(name, fixed_name_length(name));
804
 
    }
805
 
  }
806
 
 end:
807
 
  dbDisconnect(current_host);
808
 
  my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
809
 
  my_end(my_end_arg);
810
 
  return(first_error!=0);
811
 
} /* main */