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);
110
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
111
opt_ssl_capath, opt_ssl_cipher);
112
mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
113
(char*)&opt_ssl_verify_server_cert);
116
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
118
if (shared_memory_base_name)
119
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
121
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
123
if (!(mysql_real_connect(&mysql,host,user,opt_password,
124
(first_argument_uses_wildcards) ? "" :
125
argv[0],opt_mysql_port,opt_mysql_unix_port,
128
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
134
case 0: error=list_dbs(&mysql,wild); break;
137
error=list_table_status(&mysql,argv[0],wild);
139
error=list_tables(&mysql,argv[0],wild);
142
if (opt_status && ! wild)
143
error=list_table_status(&mysql,argv[0],argv[1]);
145
error=list_fields(&mysql,argv[0],argv[1],wild);
148
mysql_close(&mysql); /* Close & free connection */
150
my_free(opt_password,MYF(0));
152
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
156
return 0; /* No compiler warnings */
159
static struct my_option my_long_options[] =
161
{"character-sets-dir", 'c', "Directory where character sets are.",
162
(uchar**) &charsets_dir, (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
164
{"default-character-set", OPT_DEFAULT_CHARSET,
165
"Set the default character set.", (uchar**) &default_charset,
166
(uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
168
"Show number of rows per table (may be slow for not MyISAM tables)",
169
(uchar**) &opt_count, (uchar**) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
171
{"compress", 'C', "Use compression in server/client protocol.",
172
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
174
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
175
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
176
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
177
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
178
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
179
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
180
(uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
181
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
182
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
184
{"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR,
185
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
186
{"status", 'i', "Shows a lot of extra information about each table.",
187
(uchar**) &opt_status, (uchar**) &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
189
{"keys", 'k', "Show keys for table.", (uchar**) &opt_show_keys,
190
(uchar**) &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
192
"Password to use when connecting to server. If password is not given it's asked from the tty.",
193
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
194
{"port", 'P', "Port number to use for connection or 0 for default to, in "
195
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
196
#if MYSQL_PORT_DEFAULT == 0
199
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
200
(uchar**) &opt_mysql_port,
201
(uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
203
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
204
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
206
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
207
"Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
208
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
210
{"show-table-type", 't', "Show table type column.",
211
(uchar**) &opt_table_type, (uchar**) &opt_table_type, 0, GET_BOOL,
212
NO_ARG, 0, 0, 0, 0, 0, 0},
213
{"socket", 'S', "Socket file to use for connection.",
214
(uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
215
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
216
#ifndef DONT_ALLOW_USER_CHANGE
217
{"user", 'u', "User for login if not current user.", (uchar**) &user,
218
(uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
221
"More verbose output; You can use this multiple times to get even more verbose output.",
222
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
223
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
224
NO_ARG, 0, 0, 0, 0, 0, 0},
225
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
229
#include <help_start.h>
231
static void print_version(void)
233
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
234
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
238
static void usage(void)
241
puts("Copyright (C) 2000-2006 MySQL AB");
242
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");
243
puts("Shows the structure of a mysql database (databases,tables and columns)\n");
244
printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
246
If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\
247
what\'s matched by the wildcard is shown.\n\
248
If no database is given then all matching databases are shown.\n\
249
If no table is given then all matching tables in database are shown\n\
250
If no column is given then all matching columns and columntypes in table\n\
252
print_defaults("my",load_default_groups);
253
my_print_help(my_long_options);
254
my_print_variables(my_long_options);
257
#include <help_end.h>
260
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
270
char *start=argument;
271
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
272
opt_password=my_strdup(argument,MYF(MY_FAE));
273
while (*argument) *argument++= 'x'; /* Destroy argument */
275
start[1]=0; /* Cut length of argument */
281
case OPT_MYSQL_PROTOCOL:
282
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
286
DBUG_PUSH(argument ? argument : "d:t:o");
303
get_options(int *argc,char ***argv)
307
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
311
opt_password=get_tty_password(NullS);
315
We need to set verbose to 2 as we need to change the output to include
316
the number-of-rows column
321
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
322
if (debug_check_flag)
323
my_end_arg= MY_CHECK_ERROR;
329
list_dbs(MYSQL *mysql,const char *wild)
332
uint length, counter = 0;
334
char tables[NAME_LEN+1], rows[NAME_LEN+1];
338
MYSQL_ROW row= NULL, rrow;
340
if (!(result=mysql_list_dbs(mysql,wild)))
342
fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname,
348
If a wildcard was used, but there was only one row and it's name is an
349
exact match, we'll assume they really wanted to see the contents of that
350
database. This is because it is fairly common for database names to
351
contain the underscore (_), like INFORMATION_SCHEMA.
353
if (wild && mysql_num_rows(result) == 1)
355
row= mysql_fetch_row(result);
356
if (!my_strcasecmp(&my_charset_latin1, row[0], wild))
358
mysql_free_result(result);
360
return list_table_status(mysql, wild, NULL);
362
return list_tables(mysql, wild, NULL);
367
printf("Wildcard: %s\n",wild);
370
length=(uint) strlen(header);
371
field=mysql_fetch_field(result);
372
if (length < field->max_length)
373
length=field->max_length;
376
print_header(header,length,NullS);
377
else if (opt_verbose == 1)
378
print_header(header,length,"Tables",6,NullS);
380
print_header(header,length,"Tables",6,"Total Rows",12,NullS);
382
/* The first row may have already been read up above. */
383
while (row || (row= mysql_fetch_row(result)))
389
if (!(mysql_select_db(mysql,row[0])))
391
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
392
if (mysql_affected_rows(mysql) > 0)
394
sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql));
398
/* Print the count of tables and rows for each database */
400
while ((trow = mysql_fetch_row(tresult)))
402
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
403
if (!(mysql_query(mysql,query)))
406
if ((rresult = mysql_store_result(mysql)))
408
rrow = mysql_fetch_row(rresult);
409
rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10);
410
mysql_free_result(rresult);
414
sprintf(rows,"%12lu",rowcount);
419
sprintf(tables,"%6d",0);
420
sprintf(rows,"%12d",0);
422
mysql_free_result(tresult);
426
strmov(tables,"N/A");
432
print_row(row[0],length,0);
433
else if (opt_verbose == 1)
434
print_row(row[0],length,tables,6,NullS);
436
print_row(row[0],length,tables,6,rows,12,NullS);
441
print_trailer(length,
442
(opt_verbose > 0 ? 6 : 0),
443
(opt_verbose > 1 ? 12 :0),
446
if (counter && opt_verbose)
447
printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : "");
448
mysql_free_result(result);
454
list_tables(MYSQL *mysql,const char *db,const char *table)
457
uint head_length, counter = 0;
458
char query[255], rows[NAME_LEN], fields[16];
463
if (mysql_select_db(mysql,db))
465
fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db,
472
We just hijack the 'rows' variable for a bit to store the escaped
475
mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table));
476
my_snprintf(query, sizeof(query), "show%s tables like '%s'",
477
opt_table_type ? " full" : "", rows);
480
my_snprintf(query, sizeof(query), "show%s tables",
481
opt_table_type ? " full" : "");
482
if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql)))
484
fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db,
488
printf("Database: %s",db);
490
printf(" Wildcard: %s",table);
494
head_length=(uint) strlen(header);
495
field=mysql_fetch_field(result);
496
if (head_length < field->max_length)
497
head_length=field->max_length;
502
print_header(header,head_length,"table_type",10,NullS);
503
else if (opt_verbose == 1)
504
print_header(header,head_length,"table_type",10,"Columns",8,NullS);
507
print_header(header,head_length,"table_type",10,"Columns",8,
508
"Total Rows",10,NullS);
514
print_header(header,head_length,NullS);
515
else if (opt_verbose == 1)
516
print_header(header,head_length,"Columns",8,NullS);
518
print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
521
while ((row = mysql_fetch_row(result)))
526
if (!(mysql_select_db(mysql,db)))
528
MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL);
532
strmov(fields,"N/A");
537
sprintf(fields,"%8u",(uint) mysql_num_fields(rresult));
538
mysql_free_result(rresult);
542
/* Print the count of rows for each table */
543
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
544
if (!(mysql_query(mysql,query)))
546
if ((rresult = mysql_store_result(mysql)))
548
rrow = mysql_fetch_row(rresult);
549
rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10);
550
mysql_free_result(rresult);
552
sprintf(rows,"%10lu",rowcount);
555
sprintf(rows,"%10d",0);
561
strmov(fields,"N/A");
568
print_row(row[0],head_length,row[1],10,NullS);
569
else if (opt_verbose == 1)
570
print_row(row[0],head_length,row[1],10,fields,8,NullS);
572
print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS);
577
print_row(row[0],head_length,NullS);
578
else if (opt_verbose == 1)
579
print_row(row[0],head_length, fields,8, NullS);
581
print_row(row[0],head_length, fields,8, rows,10, NullS);
585
print_trailer(head_length,
586
(opt_table_type ? 10 : opt_verbose > 0 ? 8 : 0),
587
(opt_table_type ? (opt_verbose > 0 ? 8 : 0)
588
: (opt_verbose > 1 ? 10 :0)),
589
!opt_table_type ? 0 : opt_verbose > 1 ? 10 :0,
592
if (counter && opt_verbose)
593
printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : "");
595
mysql_free_result(result);
601
list_table_status(MYSQL *mysql,const char *db,const char *wild)
603
char query[1024],*end;
607
end=strxmov(query,"show table status from `",db,"`",NullS);
609
strxmov(end," like '",wild,"'",NullS);
610
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
612
fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n",
613
my_progname,db,wild ? wild : "",mysql_error(mysql));
614
if (mysql_errno(mysql) == ER_PARSE_ERROR)
615
fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n");
619
printf("Database: %s",db);
621
printf(" Wildcard: %s",wild);
624
print_res_header(result);
625
while ((row=mysql_fetch_row(result)))
626
print_res_row(result,row);
627
print_res_top(result);
628
mysql_free_result(result);
633
list fields uses field interface as an example of how to parse
638
list_fields(MYSQL *mysql,const char *db,const char *table,
641
char query[1024],*end;
646
if (mysql_select_db(mysql,db))
648
fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db,
655
sprintf(query,"select count(*) from `%s`", table);
656
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
658
fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
659
my_progname,db,table,mysql_error(mysql));
662
row= mysql_fetch_row(result);
663
rows= (ulong) strtoull(row[0], (char**) 0, 10);
664
mysql_free_result(result);
667
end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
669
strxmov(end," like '",wild,"'",NullS);
670
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
672
fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n",
673
my_progname,db,table,mysql_error(mysql));
677
printf("Database: %s Table: %s", db, table);
679
printf(" Rows: %lu", rows);
681
printf(" Wildcard: %s",wild);
684
print_res_header(result);
685
while ((row=mysql_fetch_row(result)))
686
print_res_row(result,row);
687
print_res_top(result);
690
end=strmov(strmov(strmov(query,"show keys from `"),table),"`");
691
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
693
fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n",
694
my_progname,db,table,mysql_error(mysql));
697
if (mysql_num_rows(result))
699
print_res_header(result);
700
while ((row=mysql_fetch_row(result)))
701
print_res_row(result,row);
702
print_res_top(result);
705
puts("Table has no keys");
707
mysql_free_result(result);
712
/*****************************************************************************
713
General functions to print a nice ascii-table from data
714
*****************************************************************************/
717
print_header(const char *header,uint head_length,...)
720
uint length,i,str_length,pre_space;
723
va_start(args,head_length);
725
field=header; length=head_length;
728
for (i=0 ; i < length+2 ; i++)
731
if (!(field=va_arg(args,char *)))
733
length=va_arg(args,uint);
738
va_start(args,head_length);
739
field=header; length=head_length;
743
str_length=(uint) strlen(field);
744
if (str_length > length)
746
pre_space=(uint) (((int) length-(int) str_length)/2)+1;
747
for (i=0 ; i < pre_space ; i++)
749
for (i = 0 ; i < str_length ; i++)
751
length=length+2-str_length-pre_space;
752
for (i=0 ; i < length ; i++)
755
if (!(field=va_arg(args,char *)))
757
length=va_arg(args,uint);
762
va_start(args,head_length);
764
field=header; length=head_length;
767
for (i=0 ; i < length+2 ; i++)
770
if (!(field=va_arg(args,char *)))
772
length=va_arg(args,uint);
780
print_row(const char *header,uint head_length,...)
784
uint i,length,field_length;
786
va_start(args,head_length);
787
field=header; length=head_length;
793
field_length=(uint) strlen(field);
794
for (i=field_length ; i <= length ; i++)
796
if (!(field=va_arg(args,char *)))
798
length=va_arg(args,uint);
807
print_trailer(uint head_length,...)
812
va_start(args,head_length);
817
for (i=0 ; i < length+2 ; i++)
820
if (!(length=va_arg(args,uint)))
828
static void print_res_header(MYSQL_RES *result)
832
print_res_top(result);
833
mysql_field_seek(result,0);
835
while ((field = mysql_fetch_field(result)))
837
printf(" %-*s|",(int) field->max_length+1,field->name);
840
print_res_top(result);
844
static void print_res_top(MYSQL_RES *result)
850
mysql_field_seek(result,0);
851
while((field = mysql_fetch_field(result)))
853
if ((length=(uint) strlen(field->name)) > field->max_length)
854
field->max_length=length;
856
length=field->max_length;
857
for (i=length+2 ; i--> 0 ; )
865
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur)
870
mysql_field_seek(result,0);
871
for (i=0 ; i < mysql_num_fields(result); i++)
873
field = mysql_fetch_field(result);
874
length=field->max_length;
875
printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");