13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/* By Jani Tolonen, 2001-04-20, MySQL, MYSQL Development Team */
16
/* By Jani Tolonen, 2001-04-20, MySQL Development Team */
18
18
#define CHECK_VERSION "2.5.0"
23
20
#include "client_priv.h"
24
#include <mystrings/m_ctype.h>
26
template class std::vector<std::string>;
22
#include <drizzle_version.h>
23
#include <mysqld_error.h>
32
28
#define EX_MYSQLERR 2
34
static DRIZZLE drizzle_connection, *sock = 0;
30
static MYSQL mysql_connection, *sock = 0;
35
31
static bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
36
32
opt_compress = 0, opt_databases = 0, opt_fast = 0,
37
33
opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
42
38
static uint verbose = 0, opt_mysql_port=0;
43
39
static int my_end_arg;
44
40
static char * opt_mysql_unix_port = 0;
45
static char *opt_password = 0, *current_user = 0,
46
*default_charset = (char *)DRIZZLE_DEFAULT_CHARSET_NAME,
41
static char *opt_password = 0, *current_user = 0,
42
*default_charset = (char *)MYSQL_DEFAULT_CHARSET_NAME,
48
44
static int first_error = 0;
49
vector<string> tables4repair;
45
DYNAMIC_ARRAY tables4repair;
50
46
static uint opt_protocol=0;
51
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
47
static CHARSET_INFO *charset_info= &my_charset_latin1;
53
49
enum operations { DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
128
124
"Password to use when connecting to server. If password is not given it's solicited on the tty.",
129
125
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
130
126
{"port", 'P', "Port number to use for connection or 0 for default to, in "
131
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
132
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
127
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
128
#if MYSQL_PORT_DEFAULT == 0
131
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
133
132
(char**) &opt_mysql_port,
134
133
(char**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
136
{"protocol", OPT_DRIZZLE_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
135
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
137
136
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
139
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.",
176
175
static int process_all_tables_in_db(char *database);
177
176
static int process_one_db(char *database);
178
177
static int use_db(char *database);
179
static int handle_request_for_tables(const char *tables, uint length);
178
static int handle_request_for_tables(char *tables, uint length);
180
179
static int dbConnect(char *host, char *user,char *passwd);
181
180
static void dbDisconnect(char *host);
182
static void DBerror(DRIZZLE *drizzle, const char *when);
181
static void DBerror(MYSQL *mysql, const char *when);
183
182
static void safe_exit(int error);
184
183
static void print_result(void);
185
184
static uint fixed_name_length(const char *name);
186
static char *fix_table_name(char *dest, const char *src);
185
static char *fix_table_name(char *dest, char *src);
187
186
int what_to_do = 0;
188
#include <help_start.h>
189
190
static void print_version(void)
191
192
printf("%s Ver %s Distrib %s, for %s (%s)\n", my_progname, CHECK_VERSION,
192
drizzle_get_client_info(), SYSTEM_TYPE, MACHINE_TYPE);
193
MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
193
194
} /* print_version */
195
197
static void usage(void)
201
203
puts("This program can be used to CHECK (-c,-m,-C), REPAIR (-r), ANALYZE (-a)");
202
204
puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be");
203
205
puts("used at the same time. Not all options are supported by all storage engines.");
204
puts("Please consult the Drizzle manual for latest information about the");
206
puts("Please consult the MySQL manual for latest information about the");
205
207
puts("above. The options -c,-r,-a and -o are exclusive to each other, which");
206
208
puts("means that the last option will be used, if several was specified.\n");
207
209
puts("The option -c will be used by default, if none was specified. You");
212
214
puts("mysqloptimize: The default option will be -o\n");
213
215
printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
214
216
printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n",
216
218
printf("OR %s [OPTIONS] --all-databases\n", my_progname);
217
219
print_defaults("my", load_default_groups);
218
220
my_print_help(my_long_options);
219
221
my_print_variables(my_long_options);
224
#include <help_end.h>
223
227
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
260
264
char *start = argument;
265
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
262
266
opt_password = my_strdup(argument, MYF(MY_FAE));
263
while (*argument) *argument++= 'x'; /* Destroy argument */
267
while (*argument) *argument++= 'x'; /* Destroy argument */
265
start[1] = 0; /* Cut length of argument */
269
start[1] = 0; /* Cut length of argument */
323
329
/* TODO: This variable is not yet used */
324
330
if (strcmp(default_charset, charset_info->csname) &&
325
!(charset_info= get_charset_by_csname(default_charset,
326
MY_CS_PRIMARY, MYF(MY_WME))))
331
!(charset_info= get_charset_by_csname(default_charset,
332
MY_CS_PRIMARY, MYF(MY_WME))))
328
334
if (*argc > 0 && opt_alldbs)
330
336
printf("You should give only options, no arguments at all, with option\n");
331
337
printf("--all-databases. Please see %s --help for more information.\n",
335
341
if (*argc < 1 && !opt_alldbs)
337
343
printf("You forgot to give the arguments! Please see %s --help\n",
339
345
printf("for more information.\n");
342
348
if (tty_password)
343
opt_password = get_tty_password(NULL);
349
opt_password = get_tty_password(NullS);
344
350
if (debug_info_flag)
345
351
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
346
352
if (debug_check_flag)
352
358
static int process_all_databases()
355
DRIZZLE_RES *tableres;
358
if (drizzle_query(sock, "SHOW DATABASES") ||
359
!(tableres = drizzle_store_result(sock)))
364
if (mysql_query(sock, "SHOW DATABASES") ||
365
!(tableres = mysql_store_result(sock)))
361
367
my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
362
MYF(0), drizzle_error(sock));
368
MYF(0), mysql_error(sock));
365
while ((row = drizzle_fetch_row(tableres)))
371
while ((row = mysql_fetch_row(tableres)))
367
373
if (process_one_db(row[0]))
391
397
if (opt_all_in_1)
394
400
We need table list in form `a`, `b`, `c`
395
401
that's why we need 2 more chars added to to each table name
396
402
space is for more readable output in logs and in case of error
398
404
char *table_names_comma_sep, *end;
399
405
int i, tot_length = 0;
402
408
tot_length+= fixed_name_length(*(table_names + i)) + 2;
404
410
if (!(table_names_comma_sep = (char *)
405
my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
411
my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
408
414
for (end = table_names_comma_sep + 1; tables > 0;
409
tables--, table_names++)
415
tables--, table_names++)
411
417
end= fix_table_name(end, *table_names);
415
421
handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1);
416
free(table_names_comma_sep);
422
my_free(table_names_comma_sep, MYF(0));
419
425
for (; tables > 0; tables--, table_names++)
464
470
static int process_all_tables_in_db(char *database)
468
474
uint num_columns;
470
476
if (use_db(database))
472
if (drizzle_query(sock, "SHOW /*!50002 FULL*/ TABLES") ||
473
!((res= drizzle_store_result(sock))))
478
if (mysql_query(sock, "SHOW /*!50002 FULL*/ TABLES") ||
479
!((res= mysql_store_result(sock))))
476
num_columns= drizzle_num_fields(res);
482
num_columns= mysql_num_fields(res);
478
484
if (opt_all_in_1)
486
492
char *tables, *end;
487
493
uint tot_length = 0;
489
while ((row = drizzle_fetch_row(res)))
495
while ((row = mysql_fetch_row(res)))
490
496
tot_length+= fixed_name_length(row[0]) + 2;
491
drizzle_data_seek(res, 0);
497
mysql_data_seek(res, 0);
493
499
if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
495
drizzle_free_result(res);
501
mysql_free_result(res);
498
for (end = tables + 1; (row = drizzle_fetch_row(res)) ;)
504
for (end = tables + 1; (row = mysql_fetch_row(res)) ;)
500
506
if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
508
514
handle_request_for_tables(tables + 1, tot_length - 1);
515
my_free(tables, MYF(0));
513
while ((row = drizzle_fetch_row(res)))
519
while ((row = mysql_fetch_row(res)))
515
521
/* Skip views if we don't perform renaming. */
516
522
if ((what_to_do != DO_UPGRADE) && (num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
532
538
if (strncmp(name, "#mysql50#", 9))
534
540
sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9);
535
if (drizzle_query(sock, qbuf))
541
if (mysql_query(sock, qbuf))
537
543
fprintf(stderr, "Failed to %s\n", qbuf);
538
fprintf(stderr, "Error: %s\n", drizzle_error(sock));
544
fprintf(stderr, "Error: %s\n", mysql_error(sock));
550
556
if (strncmp(name, "#mysql50#", 9))
552
558
sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name);
553
if (drizzle_query(sock, qbuf))
559
if (mysql_query(sock, qbuf))
555
561
fprintf(stderr, "Failed to %s\n", qbuf);
556
fprintf(stderr, "Error: %s\n", drizzle_error(sock));
562
fprintf(stderr, "Error: %s\n", mysql_error(sock));
581
587
static int use_db(char *database)
583
if (drizzle_get_server_version(sock) >= 50003 &&
584
!my_strcasecmp(&my_charset_utf8_general_ci, database, "information_schema"))
589
if (mysql_get_server_version(sock) >= 50003 &&
590
!my_strcasecmp(&my_charset_latin1, database, "information_schema"))
586
if (drizzle_select_db(sock, database))
592
if (mysql_select_db(sock, database))
588
594
DBerror(sock, "when selecting the database");
595
static int handle_request_for_tables(const char *tables, uint length)
601
static int handle_request_for_tables(char *tables, uint length)
597
603
char *query, *end, options[100], message[100];
598
604
uint query_length= 0;
603
609
switch (what_to_do) {
606
if (opt_quick) end = my_stpcpy(end, " QUICK");
607
if (opt_fast) end = my_stpcpy(end, " FAST");
608
if (opt_medium_check) end = my_stpcpy(end, " MEDIUM"); /* Default */
609
if (opt_extended) end = my_stpcpy(end, " EXTENDED");
610
if (opt_check_only_changed) end = my_stpcpy(end, " CHANGED");
611
if (opt_upgrade) end = my_stpcpy(end, " FOR UPGRADE");
612
if (opt_quick) end = strmov(end, " QUICK");
613
if (opt_fast) end = strmov(end, " FAST");
614
if (opt_medium_check) end = strmov(end, " MEDIUM"); /* Default */
615
if (opt_extended) end = strmov(end, " EXTENDED");
616
if (opt_check_only_changed) end = strmov(end, " CHANGED");
617
if (opt_upgrade) end = strmov(end, " FOR UPGRADE");
614
620
op= (opt_write_binlog) ? "REPAIR" : "REPAIR NO_WRITE_TO_BINLOG";
615
if (opt_quick) end = my_stpcpy(end, " QUICK");
616
if (opt_extended) end = my_stpcpy(end, " EXTENDED");
617
if (opt_frm) end = my_stpcpy(end, " USE_FRM");
621
if (opt_quick) end = strmov(end, " QUICK");
622
if (opt_extended) end = strmov(end, " EXTENDED");
623
if (opt_frm) end = strmov(end, " USE_FRM");
620
626
op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
640
ptr= my_stpcpy(my_stpcpy(query, op), " TABLE ");
646
ptr= strmov(strmov(query, op), " TABLE ");
641
647
ptr= fix_table_name(ptr, tables);
642
ptr= strxmov(ptr, " ", options, NULL);
648
ptr= strxmov(ptr, " ", options, NullS);
643
649
query_length= (uint) (ptr - query);
645
if (drizzle_real_query(sock, query, query_length))
651
if (mysql_real_query(sock, query, query_length))
647
653
sprintf(message, "when executing '%s TABLE ... %s'", op, options);
648
654
DBerror(sock, message);
658
my_free(query, MYF(0));
657
663
static void print_result()
661
667
char prev[NAME_LEN*2+2];
663
669
bool found_error=0;
665
res = drizzle_use_result(sock);
671
res = mysql_use_result(sock);
668
for (i = 0; (row = drizzle_fetch_row(res)); i++)
674
for (i = 0; (row = mysql_fetch_row(res)); i++)
670
676
int changed = strcmp(prev, row[0]);
671
677
bool status = !strcmp(row[2], "status");
680
686
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR &&
682
tables4repair.push_back(string(prev));
688
insert_dynamic(&tables4repair, (uchar*) prev);
687
693
if (status && changed)
688
694
printf("%-50s %s", row[0], row[3]);
691
697
printf("%s\n%-9s: %s", row[0], row[2], row[3]);
692
698
if (strcmp(row[2],"note"))
696
702
printf("%-9s: %s", row[2], row[3]);
697
my_stpcpy(prev, row[0]);
703
strmov(prev, row[0]);
700
706
/* add the last table to be repaired to the list */
701
707
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR)
702
tables4repair.push_back(string(prev));
703
drizzle_free_result(res);
708
insert_dynamic(&tables4repair, (uchar*) prev);
709
mysql_free_result(res);
712
718
fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
714
drizzle_create(&drizzle_connection);
720
mysql_init(&mysql_connection);
715
721
if (opt_compress)
716
drizzle_options(&drizzle_connection, DRIZZLE_OPT_COMPRESS, NULL);
722
mysql_options(&mysql_connection, MYSQL_OPT_COMPRESS, NullS);
717
723
if (opt_protocol)
718
drizzle_options(&drizzle_connection,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
719
if (!(sock = drizzle_connect(&drizzle_connection, host, user, passwd,
724
mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
725
if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd,
720
726
NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
722
DBerror(&drizzle_connection, "when trying to connect");
728
DBerror(&mysql_connection, "when trying to connect");
725
drizzle_connection.reconnect= 1;
731
mysql_connection.reconnect= 1;
727
733
} /* dbConnect */
733
739
fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
735
741
} /* dbDisconnect */
738
static void DBerror(DRIZZLE *drizzle, const char *when)
744
static void DBerror(MYSQL *mysql, const char *when)
740
746
my_printf_error(0,"Got error: %d: %s %s", MYF(0),
741
drizzle_errno(drizzle), drizzle_error(drizzle), when);
747
mysql_errno(mysql), mysql_error(mysql), when);
742
748
safe_exit(EX_MYSQLERR);
770
776
if (dbConnect(current_host, current_user, opt_password))
771
777
exit(EX_MYSQLERR);
779
if (opt_auto_repair &&
780
my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64))
775
tables4repair.reserve(64);
776
if (tables4repair.capacity() == 0)
785
787
process_all_databases();
786
788
/* Only one database and selected table(s) */
791
793
process_databases(argv);
792
794
if (opt_auto_repair)
795
if (!opt_silent && (tables4repair.size() > 0))
798
if (!opt_silent && tables4repair.elements)
796
799
puts("\nRepairing tables");
797
800
what_to_do = DO_REPAIR;
798
vector<string>::iterator i;
799
for ( i= tables4repair.begin() ; i < tables4repair.end() ; i++)
801
for (i = 0; i < tables4repair.elements ; i++)
801
const char *name= (*i).c_str();
803
char *name= (char*) dynamic_array_ptr(&tables4repair, i);
802
804
handle_request_for_tables(name, fixed_name_length(name));
806
808
dbDisconnect(current_host);
810
delete_dynamic(&tables4repair);
811
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
808
812
my_end(my_end_arg);
809
813
return(first_error!=0);