~drizzle-trunk/drizzle/development

206.3.1 by Patrick Galbraith
Most everything working with client rename
1
/* Copyright (C) 2008 Drizzle development team
1 by brian
clean slate
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
206.3.1 by Patrick Galbraith
Most everything working with client rename
16
/* By Jani Tolonen, 2001-04-20, MySQL, DRIZZLE Development Team */
1 by brian
clean slate
17
18
#define CHECK_VERSION "2.5.0"
19
20
#include "client_priv.h"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
21
#include <mystrings/m_ctype.h>
1 by brian
clean slate
22
23
/* Exit codes */
24
25
#define EX_USAGE 1
26
#define EX_MYSQLERR 2
27
206.3.1 by Patrick Galbraith
Most everything working with client rename
28
static DRIZZLE drizzle_connection, *sock = 0;
143 by Brian Aker
Bool cleanup.
29
static bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
1 by brian
clean slate
30
               opt_compress = 0, opt_databases = 0, opt_fast = 0,
31
               opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
32
               opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
33
               tty_password= 0, opt_frm= 0, debug_info_flag= 0, debug_check_flag= 0,
34
               opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0,
35
               opt_write_binlog= 1;
36
static uint verbose = 0, opt_mysql_port=0;
37
static int my_end_arg;
38
static char * opt_mysql_unix_port = 0;
206.3.1 by Patrick Galbraith
Most everything working with client rename
39
static char *opt_password = 0, *current_user = 0,
40
      *default_charset = (char *)MYSQL_DEFAULT_CHARSET_NAME,
41
      *current_host = 0;
1 by brian
clean slate
42
static int first_error = 0;
43
DYNAMIC_ARRAY tables4repair;
44
static uint opt_protocol=0;
45
static CHARSET_INFO *charset_info= &my_charset_latin1;
46
47
enum operations { DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
48
49
static struct my_option my_long_options[] =
50
{
51
  {"all-databases", 'A',
52
   "Check all the databases. This will be same as  --databases with all databases selected.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
53
   (char**) &opt_alldbs, (char**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1 by brian
clean slate
54
   0, 0},
55
  {"analyze", 'a', "Analyze given tables.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
56
   0, 0, 0, 0},
57
  {"all-in-1", '1',
58
   "Instead of issuing one query for each table, use one query per database, naming all tables in the database in a comma-separated list.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
59
   (char**) &opt_all_in_1, (char**) &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1 by brian
clean slate
60
   0, 0, 0},
61
  {"auto-repair", OPT_AUTO_REPAIR,
62
   "If a checked table is corrupted, automatically fix it. Repairing will be done after all tables have been checked, if corrupted ones were found.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
63
   (char**) &opt_auto_repair, (char**) &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0,
1 by brian
clean slate
64
   0, 0, 0, 0, 0},
65
  {"character-sets-dir", OPT_CHARSETS_DIR,
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
66
   "Directory where character sets are.", (char**) &charsets_dir,
67
   (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
68
  {"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
69
   0, 0, 0, 0},
70
  {"check-only-changed", 'C',
71
   "Check only tables that have changed since last check or haven't been closed properly.",
72
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
73
  {"check-upgrade", 'g',
74
   "Check tables for version-dependent changes. May be used with --auto-repair to correct tables requiring version-dependent updates.",
75
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
76
  {"compress", OPT_COMPRESS, "Use compression in server/client protocol.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
77
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1 by brian
clean slate
78
   0, 0, 0},
79
  {"databases", 'B',
80
   "To check several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
81
   (char**) &opt_databases, (char**) &opt_databases, 0, GET_BOOL, NO_ARG,
1 by brian
clean slate
82
   0, 0, 0, 0, 0, 0},
83
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
84
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
1 by brian
clean slate
85
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
86
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
87
   (char**) &debug_info_flag, (char**) &debug_info_flag,
1 by brian
clean slate
88
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
89
  {"default-character-set", OPT_DEFAULT_CHARSET,
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
90
   "Set the default character set.", (char**) &default_charset,
91
   (char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
92
  {"fast",'F', "Check only tables that haven't been closed properly.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
93
   (char**) &opt_fast, (char**) &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
1 by brian
clean slate
94
   0},
95
  {"fix-db-names", OPT_FIX_DB_NAMES, "Fix database names.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
96
    (char**) &opt_fix_db_names, (char**) &opt_fix_db_names,
1 by brian
clean slate
97
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
98
  {"fix-table-names", OPT_FIX_TABLE_NAMES, "Fix table names.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
99
    (char**) &opt_fix_table_names, (char**) &opt_fix_table_names,
1 by brian
clean slate
100
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
101
  {"force", 'f', "Continue even if we get an sql-error.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
102
   (char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
1 by brian
clean slate
103
   0, 0, 0, 0},
104
  {"extended", 'e',
105
   "If you are using this option with CHECK TABLE, it will ensure that the table is 100 percent consistent, but will take a long time. If you are using this option with REPAIR TABLE, it will force using old slow repair with keycache method, instead of much faster repair by sorting.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
106
   (char**) &opt_extended, (char**) &opt_extended, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1 by brian
clean slate
107
   0, 0, 0},
108
  {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
109
   NO_ARG, 0, 0, 0, 0, 0, 0},
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
110
  {"host",'h', "Connect to host.", (char**) &current_host,
111
   (char**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
112
  {"medium-check", 'm',
113
   "Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.",
114
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
115
  {"write-binlog", OPT_WRITE_BINLOG,
116
   "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Use --skip-write-binlog when commands should not be sent to replication slaves.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
117
   (char**) &opt_write_binlog, (char**) &opt_write_binlog, 0, GET_BOOL, NO_ARG,
1 by brian
clean slate
118
   1, 0, 0, 0, 0, 0},
119
  {"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
120
   0, 0},
121
  {"password", 'p',
122
   "Password to use when connecting to server. If password is not given it's solicited on the tty.",
123
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
124
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
125
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
126
#if MYSQL_PORT_DEFAULT == 0
127
   "/etc/services, "
128
#endif
129
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
130
   (char**) &opt_mysql_port,
131
   (char**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
1 by brian
clean slate
132
   0},
206.3.1 by Patrick Galbraith
Most everything working with client rename
133
  {"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
1 by brian
clean slate
134
   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
135
  {"quick", 'q',
136
   "If you are using this option with CHECK TABLE, it prevents the check from scanning the rows to check for wrong links. This is the fastest check. If you are using this option with REPAIR TABLE, it will try to repair only the index tree. This is the fastest repair method for a table.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
137
   (char**) &opt_quick, (char**) &opt_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
1 by brian
clean slate
138
   0},
139
  {"repair", 'r',
140
   "Can fix almost anything except unique keys that aren't unique.",
141
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
142
  {"silent", 's', "Print only error messages.", (char**) &opt_silent,
143
   (char**) &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
144
  {"socket", 'S', "Socket file to use for connection.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
145
   (char**) &opt_mysql_unix_port, (char**) &opt_mysql_unix_port, 0, GET_STR,
1 by brian
clean slate
146
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
147
  {"tables", OPT_TABLES, "Overrides option --databases (-B).", 0, 0, 0,
148
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
149
  {"use-frm", OPT_FRM,
150
   "When used with REPAIR, get table structure from .frm file, so the table can be repaired even if .MYI header is corrupted.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
151
   (char**) &opt_frm, (char**) &opt_frm, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
1 by brian
clean slate
152
   0},
153
#ifndef DONT_ALLOW_USER_CHANGE
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
154
  {"user", 'u', "User for login if not current user.", (char**) &current_user,
155
   (char**) &current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
156
#endif
157
  {"verbose", 'v', "Print info about the various stages.", 0, 0, 0, GET_NO_ARG,
158
   NO_ARG, 0, 0, 0, 0, 0, 0},
159
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
160
   NO_ARG, 0, 0, 0, 0, 0, 0},
161
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
162
};
163
164
static const char *load_default_groups[] = { "mysqlcheck", "client", 0 };
165
166
167
static void print_version(void);
168
static void usage(void);
169
static int get_options(int *argc, char ***argv);
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
170
static int process_all_databases(void);
1 by brian
clean slate
171
static int process_databases(char **db_names);
172
static int process_selected_tables(char *db, char **table_names, int tables);
173
static int process_all_tables_in_db(char *database);
174
static int process_one_db(char *database);
175
static int use_db(char *database);
176
static int handle_request_for_tables(char *tables, uint length);
177
static int dbConnect(char *host, char *user,char *passwd);
178
static void dbDisconnect(char *host);
206.3.1 by Patrick Galbraith
Most everything working with client rename
179
static void DBerror(DRIZZLE *drizzle, const char *when);
1 by brian
clean slate
180
static void safe_exit(int error);
53.2.4 by Monty Taylor
Changes so that client/ builds cleanly with no warnings.
181
static void print_result(void);
1 by brian
clean slate
182
static uint fixed_name_length(const char *name);
183
static char *fix_table_name(char *dest, char *src);
184
int what_to_do = 0;
185
186
static void print_version(void)
187
{
188
  printf("%s  Ver %s Distrib %s, for %s (%s)\n", my_progname, CHECK_VERSION,
189
   MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
190
} /* print_version */
191
192
static void usage(void)
193
{
194
  print_version();
195
  puts("By Jani Tolonen, 2001-04-20, MySQL Development Team\n");
196
  puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n");
197
  puts("and you are welcome to modify and redistribute it under the GPL license.\n");
198
  puts("This program can be used to CHECK (-c,-m,-C), REPAIR (-r), ANALYZE (-a)");
199
  puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be");
200
  puts("used at the same time. Not all options are supported by all storage engines.");
206.3.1 by Patrick Galbraith
Most everything working with client rename
201
  puts("Please consult the Drizzle manual for latest information about the");
1 by brian
clean slate
202
  puts("above. The options -c,-r,-a and -o are exclusive to each other, which");
203
  puts("means that the last option will be used, if several was specified.\n");
204
  puts("The option -c will be used by default, if none was specified. You");
205
  puts("can change the default behavior by making a symbolic link, or");
206
  puts("copying this file somewhere with another name, the alternatives are:");
207
  puts("mysqlrepair:   The default option will be -r");
208
  puts("mysqlanalyze:  The default option will be -a");
209
  puts("mysqloptimize: The default option will be -o\n");
210
  printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
211
  printf("OR     %s [OPTIONS] --databases DB1 [DB2 DB3...]\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
212
   my_progname);
1 by brian
clean slate
213
  printf("OR     %s [OPTIONS] --all-databases\n", my_progname);
214
  print_defaults("my", load_default_groups);
215
  my_print_help(my_long_options);
216
  my_print_variables(my_long_options);
217
} /* usage */
218
143 by Brian Aker
Bool cleanup.
219
static bool
1 by brian
clean slate
220
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
206.3.1 by Patrick Galbraith
Most everything working with client rename
221
         char *argument)
1 by brian
clean slate
222
{
223
  switch(optid) {
224
  case 'a':
225
    what_to_do = DO_ANALYZE;
226
    break;
227
  case 'c':
228
    what_to_do = DO_CHECK;
229
    break;
230
  case 'C':
231
    what_to_do = DO_CHECK;
232
    opt_check_only_changed = 1;
233
    break;
234
  case 'I': /* Fall through */
235
  case '?':
236
    usage();
237
    exit(0);
238
  case 'm':
239
    what_to_do = DO_CHECK;
240
    opt_medium_check = 1;
241
    break;
242
  case 'o':
243
    what_to_do = DO_OPTIMIZE;
244
    break;
245
  case OPT_FIX_DB_NAMES:
246
    what_to_do= DO_UPGRADE;
247
    default_charset= (char*) "utf8";
248
    opt_databases= 1;
249
    break;
250
  case OPT_FIX_TABLE_NAMES:
251
    what_to_do= DO_UPGRADE;
252
    default_charset= (char*) "utf8";
253
    break;
254
  case 'p':
255
    if (argument)
256
    {
257
      char *start = argument;
258
      my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
259
      opt_password = my_strdup(argument, MYF(MY_FAE));
206.3.1 by Patrick Galbraith
Most everything working with client rename
260
      while (*argument) *argument++= 'x';    /* Destroy argument */
1 by brian
clean slate
261
      if (*start)
206.3.1 by Patrick Galbraith
Most everything working with client rename
262
  start[1] = 0;                             /* Cut length of argument */
1 by brian
clean slate
263
      tty_password= 0;
264
    }
265
    else
266
      tty_password = 1;
267
    break;
268
  case 'r':
269
    what_to_do = DO_REPAIR;
270
    break;
271
  case 'g':
272
    what_to_do= DO_CHECK;
273
    opt_upgrade= 1;
274
    break;
275
  case OPT_TABLES:
276
    opt_databases = 0;
277
    break;
278
  case 'v':
279
    verbose++;
280
    break;
281
  case 'V': print_version(); exit(0);
206.3.1 by Patrick Galbraith
Most everything working with client rename
282
  case OPT_DRIZZLE_PROTOCOL:
1 by brian
clean slate
283
    opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
284
                                    opt->name);
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("my", 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) &&
206.3.1 by Patrick Galbraith
Most everything working with client rename
324
      !(charset_info= get_charset_by_csname(default_charset,
325
                MY_CS_PRIMARY, MYF(MY_WME))))
1 by brian
clean slate
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",
206.3.1 by Patrick Galbraith
Most everything working with client rename
331
     my_progname);
1 by brian
clean slate
332
    return 1;
333
  }
334
  if (*argc < 1 && !opt_alldbs)
335
  {
336
    printf("You forgot to give the arguments! Please see %s --help\n",
206.3.1 by Patrick Galbraith
Most everything working with client rename
337
     my_progname);
1 by brian
clean slate
338
    printf("for more information.\n");
339
    return 1;
340
  }
341
  if (tty_password)
342
    opt_password = get_tty_password(NullS);
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
{
206.3.1 by Patrick Galbraith
Most everything working with client rename
353
  DRIZZLE_ROW row;
354
  DRIZZLE_RES *tableres;
1 by brian
clean slate
355
  int result = 0;
356
206.3.1 by Patrick Galbraith
Most everything working with client rename
357
  if (drizzle_query(sock, "SHOW DATABASES") ||
358
      !(tableres = drizzle_store_result(sock)))
1 by brian
clean slate
359
  {
360
    my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
206.3.1 by Patrick Galbraith
Most everything working with client rename
361
        MYF(0), drizzle_error(sock));
1 by brian
clean slate
362
    return 1;
363
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
364
  while ((row = drizzle_fetch_row(tableres)))
1 by brian
clean slate
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
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
392
    /*
1 by brian
clean slate
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
206.3.1 by Patrick Galbraith
Most everything working with client rename
396
    */   
1 by brian
clean slate
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 *)
206.3.1 by Patrick Galbraith
Most everything working with client rename
404
    my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
1 by brian
clean slate
405
      return 1;
406
407
    for (end = table_names_comma_sep + 1; tables > 0;
206.3.1 by Patrick Galbraith
Most everything working with client rename
408
   tables--, table_names++)
1 by brian
clean slate
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
    my_free(table_names_comma_sep, MYF(0));
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 */
206.3.1 by Patrick Galbraith
Most everything working with client rename
428
 
1 by brian
clean slate
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, 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
{
206.3.1 by Patrick Galbraith
Most everything working with client rename
465
  DRIZZLE_RES *res;
466
  DRIZZLE_ROW row;
1 by brian
clean slate
467
  uint num_columns;
468
469
  if (use_db(database))
470
    return 1;
206.3.1 by Patrick Galbraith
Most everything working with client rename
471
  if (drizzle_query(sock, "SHOW /*!50002 FULL*/ TABLES") ||
472
  !((res= drizzle_store_result(sock))))
1 by brian
clean slate
473
    return 1;
474
206.3.1 by Patrick Galbraith
Most everything working with client rename
475
  num_columns= drizzle_num_fields(res);
1 by brian
clean slate
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
206.3.1 by Patrick Galbraith
Most everything working with client rename
488
    while ((row = drizzle_fetch_row(res)))
1 by brian
clean slate
489
      tot_length+= fixed_name_length(row[0]) + 2;
206.3.1 by Patrick Galbraith
Most everything working with client rename
490
    drizzle_data_seek(res, 0);
1 by brian
clean slate
491
492
    if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
493
    {
206.3.1 by Patrick Galbraith
Most everything working with client rename
494
      drizzle_free_result(res);
1 by brian
clean slate
495
      return 1;
496
    }
206.3.1 by Patrick Galbraith
Most everything working with client rename
497
    for (end = tables + 1; (row = drizzle_fetch_row(res)) ;)
1 by brian
clean slate
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
    my_free(tables, MYF(0));
509
  }
510
  else
511
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
512
    while ((row = drizzle_fetch_row(res)))
1 by brian
clean slate
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
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
521
  drizzle_free_result(res);
1 by brian
clean slate
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);
206.3.1 by Patrick Galbraith
Most everything working with client rename
534
  if (drizzle_query(sock, qbuf))
1 by brian
clean slate
535
  {
536
    fprintf(stderr, "Failed to %s\n", qbuf);
206.3.1 by Patrick Galbraith
Most everything working with client rename
537
    fprintf(stderr, "Error: %s\n", drizzle_error(sock));
1 by brian
clean slate
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);
206.3.1 by Patrick Galbraith
Most everything working with client rename
552
  if (drizzle_query(sock, qbuf))
1 by brian
clean slate
553
  {
554
    fprintf(stderr, "Failed to %s\n", qbuf);
206.3.1 by Patrick Galbraith
Most everything working with client rename
555
    fprintf(stderr, "Error: %s\n", drizzle_error(sock));
1 by brian
clean slate
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
{
206.3.1 by Patrick Galbraith
Most everything working with client rename
582
  if (drizzle_get_server_version(sock) >= 50003 &&
1 by brian
clean slate
583
      !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
584
    return 1;
206.3.1 by Patrick Galbraith
Most everything working with client rename
585
  if (drizzle_select_db(sock, database))
1 by brian
clean slate
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(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 = strmov(end, " QUICK");
606
    if (opt_fast)               end = strmov(end, " FAST");
607
    if (opt_medium_check)       end = strmov(end, " MEDIUM"); /* Default */
608
    if (opt_extended)           end = strmov(end, " EXTENDED");
609
    if (opt_check_only_changed) end = strmov(end, " CHANGED");
610
    if (opt_upgrade)            end = strmov(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 = strmov(end, " QUICK");
615
    if (opt_extended)           end = strmov(end, " EXTENDED");
616
    if (opt_frm)                end = strmov(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 */
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
633
    query_length= sprintf(query, "%s TABLE %s %s", op, tables, options);
1 by brian
clean slate
634
  }
635
  else
636
  {
637
    char *ptr;
638
639
    ptr= strmov(strmov(query, op), " TABLE ");
640
    ptr= fix_table_name(ptr, tables);
641
    ptr= strxmov(ptr, " ", options, NullS);
642
    query_length= (uint) (ptr - query);
643
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
644
  if (drizzle_real_query(sock, query, query_length))
1 by brian
clean slate
645
  {
646
    sprintf(message, "when executing '%s TABLE ... %s'", op, options);
647
    DBerror(sock, message);
648
    return 1;
649
  }
650
  print_result();
651
  my_free(query, MYF(0));
652
  return 0;
653
}
654
655
656
static void print_result()
657
{
206.3.1 by Patrick Galbraith
Most everything working with client rename
658
  DRIZZLE_RES *res;
659
  DRIZZLE_ROW row;
1 by brian
clean slate
660
  char prev[NAME_LEN*2+2];
661
  uint i;
143 by Brian Aker
Bool cleanup.
662
  bool found_error=0;
1 by brian
clean slate
663
206.3.1 by Patrick Galbraith
Most everything working with client rename
664
  res = drizzle_use_result(sock);
1 by brian
clean slate
665
666
  prev[0] = '\0';
206.3.1 by Patrick Galbraith
Most everything working with client rename
667
  for (i = 0; (row = drizzle_fetch_row(res)); i++)
1 by brian
clean slate
668
  {
669
    int changed = strcmp(prev, row[0]);
143 by Brian Aker
Bool cleanup.
670
    bool status = !strcmp(row[2], "status");
1 by brian
clean slate
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 &&
206.3.1 by Patrick Galbraith
Most everything working with client rename
680
    strcmp(row[3],"OK"))
681
  insert_dynamic(&tables4repair, (uchar*) prev);
1 by brian
clean slate
682
      found_error=0;
683
      if (opt_silent)
206.3.1 by Patrick Galbraith
Most everything working with client rename
684
  continue;
1 by brian
clean slate
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"))
206.3.1 by Patrick Galbraith
Most everything working with client rename
692
  found_error=1;
1 by brian
clean slate
693
    }
694
    else
695
      printf("%-9s: %s", row[2], row[3]);
696
    strmov(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
    insert_dynamic(&tables4repair, (uchar*) prev);
206.3.1 by Patrick Galbraith
Most everything working with client rename
702
  drizzle_free_result(res);
1 by brian
clean slate
703
}
704
705
706
static int dbConnect(char *host, char *user, char *passwd)
707
{
142.1.2 by Patrick
All DBUG_x removed from client/
708
1 by brian
clean slate
709
  if (verbose)
710
  {
711
    fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
712
  }
202.2.4 by Monty Taylor
Merged from Patrick.
713
  drizzle_create(&drizzle_connection);
1 by brian
clean slate
714
  if (opt_compress)
206.3.1 by Patrick Galbraith
Most everything working with client rename
715
    drizzle_options(&drizzle_connection, DRIZZLE_OPT_COMPRESS, NullS);
1 by brian
clean slate
716
  if (opt_protocol)
206.3.1 by Patrick Galbraith
Most everything working with client rename
717
    drizzle_options(&drizzle_connection,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
718
  if (!(sock = drizzle_connect(&drizzle_connection, host, user, passwd,
1 by brian
clean slate
719
         NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
720
  {
206.3.1 by Patrick Galbraith
Most everything working with client rename
721
    DBerror(&drizzle_connection, "when trying to connect");
1 by brian
clean slate
722
    return 1;
723
  }
206.3.1 by Patrick Galbraith
Most everything working with client rename
724
  drizzle_connection.reconnect= 1;
1 by brian
clean slate
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");
206.3.1 by Patrick Galbraith
Most everything working with client rename
733
  drizzle_close(sock);
1 by brian
clean slate
734
} /* dbDisconnect */
735
736
206.3.1 by Patrick Galbraith
Most everything working with client rename
737
static void DBerror(DRIZZLE *drizzle, const char *when)
1 by brian
clean slate
738
{
739
  my_printf_error(0,"Got error: %d: %s %s", MYF(0),
206.3.1 by Patrick Galbraith
Most everything working with client rename
740
      drizzle_errno(drizzle), drizzle_error(drizzle), when);
1 by brian
clean slate
741
  safe_exit(EX_MYSQLERR);
142.1.2 by Patrick
All DBUG_x removed from client/
742
  return;
1 by brian
clean slate
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)
206.3.1 by Patrick Galbraith
Most everything working with client rename
753
    drizzle_close(sock);
1 by brian
clean slate
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
      my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64))
774
  {
775
    first_error = 1;
776
    goto end;
777
  }
778
779
  if (opt_alldbs)
780
    process_all_databases();
781
  /* Only one database and selected table(s) */
782
  else if (argc > 1 && !opt_databases)
783
    process_selected_tables(*argv, (argv + 1), (argc - 1));
784
  /* One or more databases, all tables */
785
  else
786
    process_databases(argv);
787
  if (opt_auto_repair)
788
  {
789
    uint i;
790
791
    if (!opt_silent && tables4repair.elements)
792
      puts("\nRepairing tables");
793
    what_to_do = DO_REPAIR;
794
    for (i = 0; i < tables4repair.elements ; i++)
795
    {
796
      char *name= (char*) dynamic_array_ptr(&tables4repair, i);
797
      handle_request_for_tables(name, fixed_name_length(name));
798
    }
799
  }
800
 end:
801
  dbDisconnect(current_host);
802
  if (opt_auto_repair)
803
    delete_dynamic(&tables4repair);
804
  my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
805
  my_end(my_end_arg);
806
  return(first_error!=0);
807
} /* main */