1
/* Copyright (C) 2000-2006 MySQL AB
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.
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.
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 */
16
/* Show databases, tables or columns */
18
#define SHOW_VERSION "9.10"
20
#include "client_priv.h"
23
#include <mysqld_error.h>
27
static char * host=0, *opt_password=0, *user=0;
28
static my_bool opt_show_keys= 0, opt_compress= 0, opt_count=0, opt_status= 0;
29
static my_bool tty_password= 0, opt_table_type= 0;
30
static my_bool debug_info_flag= 0, debug_check_flag= 0;
31
static uint my_end_arg= 0;
32
static uint opt_verbose=0;
33
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
36
static char *shared_memory_base_name=0;
38
static uint opt_protocol=0;
40
static void get_options(int *argc,char ***argv);
41
static uint opt_mysql_port=0;
42
static int list_dbs(MYSQL *mysql,const char *wild);
43
static int list_tables(MYSQL *mysql,const char *db,const char *table);
44
static int list_table_status(MYSQL *mysql,const char *db,const char *table);
45
static int list_fields(MYSQL *mysql,const char *db,const char *table,
47
static void print_header(const char *header,uint head_length,...);
48
static void print_row(const char *header,uint head_length,...);
49
static void print_trailer(uint length,...);
50
static void print_res_header(MYSQL_RES *result);
51
static void print_res_top(MYSQL_RES *result);
52
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur);
54
static const char *load_default_groups[]= { "mysqlshow","client",0 };
55
static char * opt_mysql_unix_port=0;
57
int main(int argc, char **argv)
60
my_bool first_argument_uses_wildcards=0;
64
load_defaults("my",load_default_groups,&argc,&argv);
65
get_options(&argc,&argv);
70
char *pos= argv[argc-1], *to;
71
for (to= pos ; *pos ; pos++, to++)
76
first_argument_uses_wildcards= 1;
80
first_argument_uses_wildcards= 1;
84
first_argument_uses_wildcards= 1;
92
*to= *pos; /* just to copy a '\0' if '\\' was used */
94
if (first_argument_uses_wildcards)
96
else if (argc == 3) /* We only want one field */
101
fprintf(stderr,"%s: Too many arguments\n",my_progname);
106
mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
108
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
110
if (shared_memory_base_name)
111
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
113
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
115
if (!(mysql_real_connect(&mysql,host,user,opt_password,
116
(first_argument_uses_wildcards) ? "" :
117
argv[0],opt_mysql_port,opt_mysql_unix_port,
120
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
126
case 0: error=list_dbs(&mysql,wild); break;
129
error=list_table_status(&mysql,argv[0],wild);
131
error=list_tables(&mysql,argv[0],wild);
134
if (opt_status && ! wild)
135
error=list_table_status(&mysql,argv[0],argv[1]);
137
error=list_fields(&mysql,argv[0],argv[1],wild);
140
mysql_close(&mysql); /* Close & free connection */
142
my_free(opt_password,MYF(0));
144
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
150
static struct my_option my_long_options[] =
152
{"character-sets-dir", 'c', "Directory where character sets are.",
153
(uchar**) &charsets_dir, (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
155
{"default-character-set", OPT_DEFAULT_CHARSET,
156
"Set the default character set.", (uchar**) &default_charset,
157
(uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
159
"Show number of rows per table (may be slow for not MyISAM tables)",
160
(uchar**) &opt_count, (uchar**) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
162
{"compress", 'C', "Use compression in server/client protocol.",
163
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
165
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
166
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
167
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
168
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
169
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
170
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
171
(uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
172
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
173
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
175
{"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR,
176
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
177
{"status", 'i', "Shows a lot of extra information about each table.",
178
(uchar**) &opt_status, (uchar**) &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
180
{"keys", 'k', "Show keys for table.", (uchar**) &opt_show_keys,
181
(uchar**) &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
183
"Password to use when connecting to server. If password is not given it's asked from the tty.",
184
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
185
{"port", 'P', "Port number to use for connection or 0 for default to, in "
186
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
187
#if MYSQL_PORT_DEFAULT == 0
190
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
191
(uchar**) &opt_mysql_port,
192
(uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
194
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
195
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
197
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
198
"Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
199
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
201
{"show-table-type", 't', "Show table type column.",
202
(uchar**) &opt_table_type, (uchar**) &opt_table_type, 0, GET_BOOL,
203
NO_ARG, 0, 0, 0, 0, 0, 0},
204
{"socket", 'S', "Socket file to use for connection.",
205
(uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
206
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
207
#ifndef DONT_ALLOW_USER_CHANGE
208
{"user", 'u', "User for login if not current user.", (uchar**) &user,
209
(uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
212
"More verbose output; You can use this multiple times to get even more verbose output.",
213
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
214
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
215
NO_ARG, 0, 0, 0, 0, 0, 0},
216
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
220
#include <help_start.h>
222
static void print_version(void)
224
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
225
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
229
static void usage(void)
232
puts("Copyright (C) 2000-2006 MySQL AB");
233
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
234
puts("Shows the structure of a mysql database (databases,tables and columns)\n");
235
printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
237
If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\
238
what\'s matched by the wildcard is shown.\n\
239
If no database is given then all matching databases are shown.\n\
240
If no table is given then all matching tables in database are shown\n\
241
If no column is given then all matching columns and columntypes in table\n\
243
print_defaults("my",load_default_groups);
244
my_print_help(my_long_options);
245
my_print_variables(my_long_options);
248
#include <help_end.h>
251
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
261
char *start=argument;
262
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
263
opt_password=my_strdup(argument,MYF(MY_FAE));
264
while (*argument) *argument++= 'x'; /* Destroy argument */
266
start[1]=0; /* Cut length of argument */
272
case OPT_MYSQL_PROTOCOL:
273
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
277
DBUG_PUSH(argument ? argument : "d:t:o");
294
get_options(int *argc,char ***argv)
298
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
302
opt_password=get_tty_password(NullS);
306
We need to set verbose to 2 as we need to change the output to include
307
the number-of-rows column
312
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
313
if (debug_check_flag)
314
my_end_arg= MY_CHECK_ERROR;
320
list_dbs(MYSQL *mysql,const char *wild)
323
uint length, counter = 0;
325
char tables[NAME_LEN+1], rows[NAME_LEN+1];
329
MYSQL_ROW row= NULL, rrow;
331
if (!(result=mysql_list_dbs(mysql,wild)))
333
fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname,
339
If a wildcard was used, but there was only one row and it's name is an
340
exact match, we'll assume they really wanted to see the contents of that
341
database. This is because it is fairly common for database names to
342
contain the underscore (_), like INFORMATION_SCHEMA.
344
if (wild && mysql_num_rows(result) == 1)
346
row= mysql_fetch_row(result);
347
if (!my_strcasecmp(&my_charset_latin1, row[0], wild))
349
mysql_free_result(result);
351
return list_table_status(mysql, wild, NULL);
353
return list_tables(mysql, wild, NULL);
358
printf("Wildcard: %s\n",wild);
361
length=(uint) strlen(header);
362
field=mysql_fetch_field(result);
363
if (length < field->max_length)
364
length=field->max_length;
367
print_header(header,length,NullS);
368
else if (opt_verbose == 1)
369
print_header(header,length,"Tables",6,NullS);
371
print_header(header,length,"Tables",6,"Total Rows",12,NullS);
373
/* The first row may have already been read up above. */
374
while (row || (row= mysql_fetch_row(result)))
380
if (!(mysql_select_db(mysql,row[0])))
382
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
383
if (mysql_affected_rows(mysql) > 0)
385
sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql));
389
/* Print the count of tables and rows for each database */
391
while ((trow = mysql_fetch_row(tresult)))
393
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
394
if (!(mysql_query(mysql,query)))
397
if ((rresult = mysql_store_result(mysql)))
399
rrow = mysql_fetch_row(rresult);
400
rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10);
401
mysql_free_result(rresult);
405
sprintf(rows,"%12lu",rowcount);
410
sprintf(tables,"%6d",0);
411
sprintf(rows,"%12d",0);
413
mysql_free_result(tresult);
417
strmov(tables,"N/A");
423
print_row(row[0],length,0);
424
else if (opt_verbose == 1)
425
print_row(row[0],length,tables,6,NullS);
427
print_row(row[0],length,tables,6,rows,12,NullS);
432
print_trailer(length,
433
(opt_verbose > 0 ? 6 : 0),
434
(opt_verbose > 1 ? 12 :0),
437
if (counter && opt_verbose)
438
printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : "");
439
mysql_free_result(result);
445
list_tables(MYSQL *mysql,const char *db,const char *table)
448
uint head_length, counter = 0;
449
char query[255], rows[NAME_LEN], fields[16];
454
if (mysql_select_db(mysql,db))
456
fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db,
463
We just hijack the 'rows' variable for a bit to store the escaped
466
mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table));
467
snprintf(query, sizeof(query), "show%s tables like '%s'",
468
opt_table_type ? " full" : "", rows);
471
snprintf(query, sizeof(query), "show%s tables",
472
opt_table_type ? " full" : "");
473
if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql)))
475
fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db,
479
printf("Database: %s",db);
481
printf(" Wildcard: %s",table);
485
head_length=(uint) strlen(header);
486
field=mysql_fetch_field(result);
487
if (head_length < field->max_length)
488
head_length=field->max_length;
493
print_header(header,head_length,"table_type",10,NullS);
494
else if (opt_verbose == 1)
495
print_header(header,head_length,"table_type",10,"Columns",8,NullS);
498
print_header(header,head_length,"table_type",10,"Columns",8,
499
"Total Rows",10,NullS);
505
print_header(header,head_length,NullS);
506
else if (opt_verbose == 1)
507
print_header(header,head_length,"Columns",8,NullS);
509
print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
512
while ((row = mysql_fetch_row(result)))
517
if (!(mysql_select_db(mysql,db)))
519
MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL);
523
strmov(fields,"N/A");
528
sprintf(fields,"%8u",(uint) mysql_num_fields(rresult));
529
mysql_free_result(rresult);
533
/* Print the count of rows for each table */
534
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
535
if (!(mysql_query(mysql,query)))
537
if ((rresult = mysql_store_result(mysql)))
539
rrow = mysql_fetch_row(rresult);
540
rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10);
541
mysql_free_result(rresult);
543
sprintf(rows,"%10lu",rowcount);
546
sprintf(rows,"%10d",0);
552
strmov(fields,"N/A");
559
print_row(row[0],head_length,row[1],10,NullS);
560
else if (opt_verbose == 1)
561
print_row(row[0],head_length,row[1],10,fields,8,NullS);
563
print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS);
568
print_row(row[0],head_length,NullS);
569
else if (opt_verbose == 1)
570
print_row(row[0],head_length, fields,8, NullS);
572
print_row(row[0],head_length, fields,8, rows,10, NullS);
576
print_trailer(head_length,
577
(opt_table_type ? 10 : opt_verbose > 0 ? 8 : 0),
578
(opt_table_type ? (opt_verbose > 0 ? 8 : 0)
579
: (opt_verbose > 1 ? 10 :0)),
580
!opt_table_type ? 0 : opt_verbose > 1 ? 10 :0,
583
if (counter && opt_verbose)
584
printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : "");
586
mysql_free_result(result);
592
list_table_status(MYSQL *mysql,const char *db,const char *wild)
594
char query[1024],*end;
598
end=strxmov(query,"show table status from `",db,"`",NullS);
600
strxmov(end," like '",wild,"'",NullS);
601
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
603
fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n",
604
my_progname,db,wild ? wild : "",mysql_error(mysql));
605
if (mysql_errno(mysql) == ER_PARSE_ERROR)
606
fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n");
610
printf("Database: %s",db);
612
printf(" Wildcard: %s",wild);
615
print_res_header(result);
616
while ((row=mysql_fetch_row(result)))
617
print_res_row(result,row);
618
print_res_top(result);
619
mysql_free_result(result);
624
list fields uses field interface as an example of how to parse
629
list_fields(MYSQL *mysql,const char *db,const char *table,
632
char query[1024],*end;
637
if (mysql_select_db(mysql,db))
639
fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db,
646
sprintf(query,"select count(*) from `%s`", table);
647
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
649
fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
650
my_progname,db,table,mysql_error(mysql));
653
row= mysql_fetch_row(result);
654
rows= (ulong) strtoull(row[0], (char**) 0, 10);
655
mysql_free_result(result);
658
end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
660
strxmov(end," like '",wild,"'",NullS);
661
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
663
fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n",
664
my_progname,db,table,mysql_error(mysql));
668
printf("Database: %s Table: %s", db, table);
670
printf(" Rows: %lu", rows);
672
printf(" Wildcard: %s",wild);
675
print_res_header(result);
676
while ((row=mysql_fetch_row(result)))
677
print_res_row(result,row);
678
print_res_top(result);
681
end=strmov(strmov(strmov(query,"show keys from `"),table),"`");
682
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
684
fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n",
685
my_progname,db,table,mysql_error(mysql));
688
if (mysql_num_rows(result))
690
print_res_header(result);
691
while ((row=mysql_fetch_row(result)))
692
print_res_row(result,row);
693
print_res_top(result);
696
puts("Table has no keys");
698
mysql_free_result(result);
703
/*****************************************************************************
704
General functions to print a nice ascii-table from data
705
*****************************************************************************/
708
print_header(const char *header,uint head_length,...)
711
uint length,i,str_length,pre_space;
714
va_start(args,head_length);
716
field=header; length=head_length;
719
for (i=0 ; i < length+2 ; i++)
722
if (!(field=va_arg(args,char *)))
724
length=va_arg(args,uint);
729
va_start(args,head_length);
730
field=header; length=head_length;
734
str_length=(uint) strlen(field);
735
if (str_length > length)
737
pre_space=(uint) (((int) length-(int) str_length)/2)+1;
738
for (i=0 ; i < pre_space ; i++)
740
for (i = 0 ; i < str_length ; i++)
742
length=length+2-str_length-pre_space;
743
for (i=0 ; i < length ; i++)
746
if (!(field=va_arg(args,char *)))
748
length=va_arg(args,uint);
753
va_start(args,head_length);
755
field=header; length=head_length;
758
for (i=0 ; i < length+2 ; i++)
761
if (!(field=va_arg(args,char *)))
763
length=va_arg(args,uint);
771
print_row(const char *header,uint head_length,...)
775
uint i,length,field_length;
777
va_start(args,head_length);
778
field=header; length=head_length;
784
field_length=(uint) strlen(field);
785
for (i=field_length ; i <= length ; i++)
787
if (!(field=va_arg(args,char *)))
789
length=va_arg(args,uint);
798
print_trailer(uint head_length,...)
803
va_start(args,head_length);
808
for (i=0 ; i < length+2 ; i++)
811
if (!(length=va_arg(args,uint)))
819
static void print_res_header(MYSQL_RES *result)
823
print_res_top(result);
824
mysql_field_seek(result,0);
826
while ((field = mysql_fetch_field(result)))
828
printf(" %-*s|",(int) field->max_length+1,field->name);
831
print_res_top(result);
835
static void print_res_top(MYSQL_RES *result)
841
mysql_field_seek(result,0);
842
while((field = mysql_fetch_field(result)))
844
if ((length=(uint) strlen(field->name)) > field->max_length)
845
field->max_length=length;
847
length=field->max_length;
848
for (i=length+2 ; i--> 0 ; )
856
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur)
861
mysql_field_seek(result,0);
862
for (i=0 ; i < mysql_num_fields(result); i++)
864
field = mysql_fetch_field(result);
865
length=field->max_length;
866
printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");