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"
24
#include <mysqld_error.h>
28
static char * host=0, *opt_password=0, *user=0;
29
static my_bool opt_show_keys= 0, opt_compress= 0, opt_count=0, opt_status= 0;
30
static my_bool tty_password= 0, opt_table_type= 0;
31
static my_bool debug_info_flag= 0, debug_check_flag= 0;
32
static uint my_end_arg= 0;
33
static uint opt_verbose=0;
34
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
37
static char *shared_memory_base_name=0;
39
static uint opt_protocol=0;
41
static void get_options(int *argc,char ***argv);
42
static uint opt_mysql_port=0;
43
static int list_dbs(MYSQL *mysql,const char *wild);
44
static int list_tables(MYSQL *mysql,const char *db,const char *table);
45
static int list_table_status(MYSQL *mysql,const char *db,const char *table);
46
static int list_fields(MYSQL *mysql,const char *db,const char *table,
48
static void print_header(const char *header,uint head_length,...);
49
static void print_row(const char *header,uint head_length,...);
50
static void print_trailer(uint length,...);
51
static void print_res_header(MYSQL_RES *result);
52
static void print_res_top(MYSQL_RES *result);
53
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur);
55
static const char *load_default_groups[]= { "mysqlshow","client",0 };
56
static char * opt_mysql_unix_port=0;
58
int main(int argc, char **argv)
61
my_bool first_argument_uses_wildcards=0;
65
load_defaults("my",load_default_groups,&argc,&argv);
66
get_options(&argc,&argv);
71
char *pos= argv[argc-1], *to;
72
for (to= pos ; *pos ; pos++, to++)
77
first_argument_uses_wildcards= 1;
81
first_argument_uses_wildcards= 1;
85
first_argument_uses_wildcards= 1;
93
*to= *pos; /* just to copy a '\0' if '\\' was used */
95
if (first_argument_uses_wildcards)
97
else if (argc == 3) /* We only want one field */
102
fprintf(stderr,"%s: Too many arguments\n",my_progname);
107
mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
109
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
111
if (shared_memory_base_name)
112
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
114
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
116
if (!(mysql_real_connect(&mysql,host,user,opt_password,
117
(first_argument_uses_wildcards) ? "" :
118
argv[0],opt_mysql_port,opt_mysql_unix_port,
121
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
127
case 0: error=list_dbs(&mysql,wild); break;
130
error=list_table_status(&mysql,argv[0],wild);
132
error=list_tables(&mysql,argv[0],wild);
135
if (opt_status && ! wild)
136
error=list_table_status(&mysql,argv[0],argv[1]);
138
error=list_fields(&mysql,argv[0],argv[1],wild);
141
mysql_close(&mysql); /* Close & free connection */
143
my_free(opt_password,MYF(0));
145
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
149
return 0; /* No compiler warnings */
152
static struct my_option my_long_options[] =
154
{"character-sets-dir", 'c', "Directory where character sets are.",
155
(uchar**) &charsets_dir, (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
157
{"default-character-set", OPT_DEFAULT_CHARSET,
158
"Set the default character set.", (uchar**) &default_charset,
159
(uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
161
"Show number of rows per table (may be slow for not MyISAM tables)",
162
(uchar**) &opt_count, (uchar**) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
164
{"compress", 'C', "Use compression in server/client protocol.",
165
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
167
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
168
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
169
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
170
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
171
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
172
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
173
(uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
174
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
175
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
177
{"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR,
178
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
179
{"status", 'i', "Shows a lot of extra information about each table.",
180
(uchar**) &opt_status, (uchar**) &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
182
{"keys", 'k', "Show keys for table.", (uchar**) &opt_show_keys,
183
(uchar**) &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
185
"Password to use when connecting to server. If password is not given it's asked from the tty.",
186
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
187
{"port", 'P', "Port number to use for connection or 0 for default to, in "
188
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
189
#if MYSQL_PORT_DEFAULT == 0
192
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
193
(uchar**) &opt_mysql_port,
194
(uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
196
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
197
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
199
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
200
"Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
201
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
203
{"show-table-type", 't', "Show table type column.",
204
(uchar**) &opt_table_type, (uchar**) &opt_table_type, 0, GET_BOOL,
205
NO_ARG, 0, 0, 0, 0, 0, 0},
206
{"socket", 'S', "Socket file to use for connection.",
207
(uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
208
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
209
#ifndef DONT_ALLOW_USER_CHANGE
210
{"user", 'u', "User for login if not current user.", (uchar**) &user,
211
(uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
214
"More verbose output; You can use this multiple times to get even more verbose output.",
215
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
216
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
217
NO_ARG, 0, 0, 0, 0, 0, 0},
218
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
222
#include <help_start.h>
224
static void print_version(void)
226
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
227
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
231
static void usage(void)
234
puts("Copyright (C) 2000-2006 MySQL AB");
235
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");
236
puts("Shows the structure of a mysql database (databases,tables and columns)\n");
237
printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
239
If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\
240
what\'s matched by the wildcard is shown.\n\
241
If no database is given then all matching databases are shown.\n\
242
If no table is given then all matching tables in database are shown\n\
243
If no column is given then all matching columns and columntypes in table\n\
245
print_defaults("my",load_default_groups);
246
my_print_help(my_long_options);
247
my_print_variables(my_long_options);
250
#include <help_end.h>
253
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
263
char *start=argument;
264
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
265
opt_password=my_strdup(argument,MYF(MY_FAE));
266
while (*argument) *argument++= 'x'; /* Destroy argument */
268
start[1]=0; /* Cut length of argument */
274
case OPT_MYSQL_PROTOCOL:
275
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
279
DBUG_PUSH(argument ? argument : "d:t:o");
296
get_options(int *argc,char ***argv)
300
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
304
opt_password=get_tty_password(NullS);
308
We need to set verbose to 2 as we need to change the output to include
309
the number-of-rows column
314
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
315
if (debug_check_flag)
316
my_end_arg= MY_CHECK_ERROR;
322
list_dbs(MYSQL *mysql,const char *wild)
325
uint length, counter = 0;
327
char tables[NAME_LEN+1], rows[NAME_LEN+1];
331
MYSQL_ROW row= NULL, rrow;
333
if (!(result=mysql_list_dbs(mysql,wild)))
335
fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname,
341
If a wildcard was used, but there was only one row and it's name is an
342
exact match, we'll assume they really wanted to see the contents of that
343
database. This is because it is fairly common for database names to
344
contain the underscore (_), like INFORMATION_SCHEMA.
346
if (wild && mysql_num_rows(result) == 1)
348
row= mysql_fetch_row(result);
349
if (!my_strcasecmp(&my_charset_latin1, row[0], wild))
351
mysql_free_result(result);
353
return list_table_status(mysql, wild, NULL);
355
return list_tables(mysql, wild, NULL);
360
printf("Wildcard: %s\n",wild);
363
length=(uint) strlen(header);
364
field=mysql_fetch_field(result);
365
if (length < field->max_length)
366
length=field->max_length;
369
print_header(header,length,NullS);
370
else if (opt_verbose == 1)
371
print_header(header,length,"Tables",6,NullS);
373
print_header(header,length,"Tables",6,"Total Rows",12,NullS);
375
/* The first row may have already been read up above. */
376
while (row || (row= mysql_fetch_row(result)))
382
if (!(mysql_select_db(mysql,row[0])))
384
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
385
if (mysql_affected_rows(mysql) > 0)
387
sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql));
391
/* Print the count of tables and rows for each database */
393
while ((trow = mysql_fetch_row(tresult)))
395
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
396
if (!(mysql_query(mysql,query)))
399
if ((rresult = mysql_store_result(mysql)))
401
rrow = mysql_fetch_row(rresult);
402
rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10);
403
mysql_free_result(rresult);
407
sprintf(rows,"%12lu",rowcount);
412
sprintf(tables,"%6d",0);
413
sprintf(rows,"%12d",0);
415
mysql_free_result(tresult);
419
strmov(tables,"N/A");
425
print_row(row[0],length,0);
426
else if (opt_verbose == 1)
427
print_row(row[0],length,tables,6,NullS);
429
print_row(row[0],length,tables,6,rows,12,NullS);
434
print_trailer(length,
435
(opt_verbose > 0 ? 6 : 0),
436
(opt_verbose > 1 ? 12 :0),
439
if (counter && opt_verbose)
440
printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : "");
441
mysql_free_result(result);
447
list_tables(MYSQL *mysql,const char *db,const char *table)
450
uint head_length, counter = 0;
451
char query[255], rows[NAME_LEN], fields[16];
456
if (mysql_select_db(mysql,db))
458
fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db,
465
We just hijack the 'rows' variable for a bit to store the escaped
468
mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table));
469
my_snprintf(query, sizeof(query), "show%s tables like '%s'",
470
opt_table_type ? " full" : "", rows);
473
my_snprintf(query, sizeof(query), "show%s tables",
474
opt_table_type ? " full" : "");
475
if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql)))
477
fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db,
481
printf("Database: %s",db);
483
printf(" Wildcard: %s",table);
487
head_length=(uint) strlen(header);
488
field=mysql_fetch_field(result);
489
if (head_length < field->max_length)
490
head_length=field->max_length;
495
print_header(header,head_length,"table_type",10,NullS);
496
else if (opt_verbose == 1)
497
print_header(header,head_length,"table_type",10,"Columns",8,NullS);
500
print_header(header,head_length,"table_type",10,"Columns",8,
501
"Total Rows",10,NullS);
507
print_header(header,head_length,NullS);
508
else if (opt_verbose == 1)
509
print_header(header,head_length,"Columns",8,NullS);
511
print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
514
while ((row = mysql_fetch_row(result)))
519
if (!(mysql_select_db(mysql,db)))
521
MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL);
525
strmov(fields,"N/A");
530
sprintf(fields,"%8u",(uint) mysql_num_fields(rresult));
531
mysql_free_result(rresult);
535
/* Print the count of rows for each table */
536
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
537
if (!(mysql_query(mysql,query)))
539
if ((rresult = mysql_store_result(mysql)))
541
rrow = mysql_fetch_row(rresult);
542
rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10);
543
mysql_free_result(rresult);
545
sprintf(rows,"%10lu",rowcount);
548
sprintf(rows,"%10d",0);
554
strmov(fields,"N/A");
561
print_row(row[0],head_length,row[1],10,NullS);
562
else if (opt_verbose == 1)
563
print_row(row[0],head_length,row[1],10,fields,8,NullS);
565
print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS);
570
print_row(row[0],head_length,NullS);
571
else if (opt_verbose == 1)
572
print_row(row[0],head_length, fields,8, NullS);
574
print_row(row[0],head_length, fields,8, rows,10, NullS);
578
print_trailer(head_length,
579
(opt_table_type ? 10 : opt_verbose > 0 ? 8 : 0),
580
(opt_table_type ? (opt_verbose > 0 ? 8 : 0)
581
: (opt_verbose > 1 ? 10 :0)),
582
!opt_table_type ? 0 : opt_verbose > 1 ? 10 :0,
585
if (counter && opt_verbose)
586
printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : "");
588
mysql_free_result(result);
594
list_table_status(MYSQL *mysql,const char *db,const char *wild)
596
char query[1024],*end;
600
end=strxmov(query,"show table status from `",db,"`",NullS);
602
strxmov(end," like '",wild,"'",NullS);
603
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
605
fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n",
606
my_progname,db,wild ? wild : "",mysql_error(mysql));
607
if (mysql_errno(mysql) == ER_PARSE_ERROR)
608
fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n");
612
printf("Database: %s",db);
614
printf(" Wildcard: %s",wild);
617
print_res_header(result);
618
while ((row=mysql_fetch_row(result)))
619
print_res_row(result,row);
620
print_res_top(result);
621
mysql_free_result(result);
626
list fields uses field interface as an example of how to parse
631
list_fields(MYSQL *mysql,const char *db,const char *table,
634
char query[1024],*end;
639
if (mysql_select_db(mysql,db))
641
fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db,
648
sprintf(query,"select count(*) from `%s`", table);
649
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
651
fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
652
my_progname,db,table,mysql_error(mysql));
655
row= mysql_fetch_row(result);
656
rows= (ulong) strtoull(row[0], (char**) 0, 10);
657
mysql_free_result(result);
660
end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
662
strxmov(end," like '",wild,"'",NullS);
663
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
665
fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n",
666
my_progname,db,table,mysql_error(mysql));
670
printf("Database: %s Table: %s", db, table);
672
printf(" Rows: %lu", rows);
674
printf(" Wildcard: %s",wild);
677
print_res_header(result);
678
while ((row=mysql_fetch_row(result)))
679
print_res_row(result,row);
680
print_res_top(result);
683
end=strmov(strmov(strmov(query,"show keys from `"),table),"`");
684
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
686
fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n",
687
my_progname,db,table,mysql_error(mysql));
690
if (mysql_num_rows(result))
692
print_res_header(result);
693
while ((row=mysql_fetch_row(result)))
694
print_res_row(result,row);
695
print_res_top(result);
698
puts("Table has no keys");
700
mysql_free_result(result);
705
/*****************************************************************************
706
General functions to print a nice ascii-table from data
707
*****************************************************************************/
710
print_header(const char *header,uint head_length,...)
713
uint length,i,str_length,pre_space;
716
va_start(args,head_length);
718
field=header; length=head_length;
721
for (i=0 ; i < length+2 ; i++)
724
if (!(field=va_arg(args,char *)))
726
length=va_arg(args,uint);
731
va_start(args,head_length);
732
field=header; length=head_length;
736
str_length=(uint) strlen(field);
737
if (str_length > length)
739
pre_space=(uint) (((int) length-(int) str_length)/2)+1;
740
for (i=0 ; i < pre_space ; i++)
742
for (i = 0 ; i < str_length ; i++)
744
length=length+2-str_length-pre_space;
745
for (i=0 ; i < length ; i++)
748
if (!(field=va_arg(args,char *)))
750
length=va_arg(args,uint);
755
va_start(args,head_length);
757
field=header; length=head_length;
760
for (i=0 ; i < length+2 ; i++)
763
if (!(field=va_arg(args,char *)))
765
length=va_arg(args,uint);
773
print_row(const char *header,uint head_length,...)
777
uint i,length,field_length;
779
va_start(args,head_length);
780
field=header; length=head_length;
786
field_length=(uint) strlen(field);
787
for (i=field_length ; i <= length ; i++)
789
if (!(field=va_arg(args,char *)))
791
length=va_arg(args,uint);
800
print_trailer(uint head_length,...)
805
va_start(args,head_length);
810
for (i=0 ; i < length+2 ; i++)
813
if (!(length=va_arg(args,uint)))
821
static void print_res_header(MYSQL_RES *result)
825
print_res_top(result);
826
mysql_field_seek(result,0);
828
while ((field = mysql_fetch_field(result)))
830
printf(" %-*s|",(int) field->max_length+1,field->name);
833
print_res_top(result);
837
static void print_res_top(MYSQL_RES *result)
843
mysql_field_seek(result,0);
844
while((field = mysql_fetch_field(result)))
846
if ((length=(uint) strlen(field->name)) > field->max_length)
847
field->max_length=length;
849
length=field->max_length;
850
for (i=length+2 ; i--> 0 ; )
858
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur)
863
mysql_field_seek(result,0);
864
for (i=0 ; i < mysql_num_fields(result); i++)
866
field = mysql_fetch_field(result);
867
length=field->max_length;
868
printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");