~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzlecheck.cc

  • Committer: Monty Taylor
  • Date: 2009-07-27 17:30:05 UTC
  • mto: (1093.7.1 captain)
  • mto: This revision was merged to the branch mainline in revision 1101.
  • Revision ID: mordred@inaugust.com-20090727173005-ohhbhnifbo1qh3hw
Removed drizzlecheck program and the myisamcheck test.

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