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));
151
static struct my_option my_long_options[] =
153
{"character-sets-dir", 'c', "Directory where character sets are.",
154
(uchar**) &charsets_dir, (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
156
{"default-character-set", OPT_DEFAULT_CHARSET,
157
"Set the default character set.", (uchar**) &default_charset,
158
(uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
160
"Show number of rows per table (may be slow for not MyISAM tables)",
161
(uchar**) &opt_count, (uchar**) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
163
{"compress", 'C', "Use compression in server/client protocol.",
164
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
166
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
167
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
168
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
169
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
170
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
171
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
172
(uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
173
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
174
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
176
{"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR,
177
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
178
{"status", 'i', "Shows a lot of extra information about each table.",
179
(uchar**) &opt_status, (uchar**) &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
181
{"keys", 'k', "Show keys for table.", (uchar**) &opt_show_keys,
182
(uchar**) &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
184
"Password to use when connecting to server. If password is not given it's asked from the tty.",
185
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
186
{"port", 'P', "Port number to use for connection or 0 for default to, in "
187
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
188
#if MYSQL_PORT_DEFAULT == 0
191
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
192
(uchar**) &opt_mysql_port,
193
(uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
195
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
196
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
198
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
199
"Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
200
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
202
{"show-table-type", 't', "Show table type column.",
203
(uchar**) &opt_table_type, (uchar**) &opt_table_type, 0, GET_BOOL,
204
NO_ARG, 0, 0, 0, 0, 0, 0},
205
{"socket", 'S', "Socket file to use for connection.",
206
(uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
207
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
208
#ifndef DONT_ALLOW_USER_CHANGE
209
{"user", 'u', "User for login if not current user.", (uchar**) &user,
210
(uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
213
"More verbose output; You can use this multiple times to get even more verbose output.",
214
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
215
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
216
NO_ARG, 0, 0, 0, 0, 0, 0},
217
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
221
#include <help_start.h>
223
static void print_version(void)
225
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
226
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
230
static void usage(void)
233
puts("Copyright (C) 2000-2006 MySQL AB");
234
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");
235
puts("Shows the structure of a mysql database (databases,tables and columns)\n");
236
printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
238
If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\
239
what\'s matched by the wildcard is shown.\n\
240
If no database is given then all matching databases are shown.\n\
241
If no table is given then all matching tables in database are shown\n\
242
If no column is given then all matching columns and columntypes in table\n\
244
print_defaults("my",load_default_groups);
245
my_print_help(my_long_options);
246
my_print_variables(my_long_options);
249
#include <help_end.h>
252
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
262
char *start=argument;
263
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
264
opt_password=my_strdup(argument,MYF(MY_FAE));
265
while (*argument) *argument++= 'x'; /* Destroy argument */
267
start[1]=0; /* Cut length of argument */
273
case OPT_MYSQL_PROTOCOL:
274
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
278
DBUG_PUSH(argument ? argument : "d:t:o");
295
get_options(int *argc,char ***argv)
299
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
303
opt_password=get_tty_password(NullS);
307
We need to set verbose to 2 as we need to change the output to include
308
the number-of-rows column
313
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
314
if (debug_check_flag)
315
my_end_arg= MY_CHECK_ERROR;
321
list_dbs(MYSQL *mysql,const char *wild)
324
uint length, counter = 0;
326
char tables[NAME_LEN+1], rows[NAME_LEN+1];
330
MYSQL_ROW row= NULL, rrow;
332
if (!(result=mysql_list_dbs(mysql,wild)))
334
fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname,
340
If a wildcard was used, but there was only one row and it's name is an
341
exact match, we'll assume they really wanted to see the contents of that
342
database. This is because it is fairly common for database names to
343
contain the underscore (_), like INFORMATION_SCHEMA.
345
if (wild && mysql_num_rows(result) == 1)
347
row= mysql_fetch_row(result);
348
if (!my_strcasecmp(&my_charset_latin1, row[0], wild))
350
mysql_free_result(result);
352
return list_table_status(mysql, wild, NULL);
354
return list_tables(mysql, wild, NULL);
359
printf("Wildcard: %s\n",wild);
362
length=(uint) strlen(header);
363
field=mysql_fetch_field(result);
364
if (length < field->max_length)
365
length=field->max_length;
368
print_header(header,length,NullS);
369
else if (opt_verbose == 1)
370
print_header(header,length,"Tables",6,NullS);
372
print_header(header,length,"Tables",6,"Total Rows",12,NullS);
374
/* The first row may have already been read up above. */
375
while (row || (row= mysql_fetch_row(result)))
381
if (!(mysql_select_db(mysql,row[0])))
383
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
384
if (mysql_affected_rows(mysql) > 0)
386
sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql));
390
/* Print the count of tables and rows for each database */
392
while ((trow = mysql_fetch_row(tresult)))
394
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
395
if (!(mysql_query(mysql,query)))
398
if ((rresult = mysql_store_result(mysql)))
400
rrow = mysql_fetch_row(rresult);
401
rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10);
402
mysql_free_result(rresult);
406
sprintf(rows,"%12lu",rowcount);
411
sprintf(tables,"%6d",0);
412
sprintf(rows,"%12d",0);
414
mysql_free_result(tresult);
418
strmov(tables,"N/A");
424
print_row(row[0],length,0);
425
else if (opt_verbose == 1)
426
print_row(row[0],length,tables,6,NullS);
428
print_row(row[0],length,tables,6,rows,12,NullS);
433
print_trailer(length,
434
(opt_verbose > 0 ? 6 : 0),
435
(opt_verbose > 1 ? 12 :0),
438
if (counter && opt_verbose)
439
printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : "");
440
mysql_free_result(result);
446
list_tables(MYSQL *mysql,const char *db,const char *table)
449
uint head_length, counter = 0;
450
char query[255], rows[NAME_LEN], fields[16];
455
if (mysql_select_db(mysql,db))
457
fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db,
464
We just hijack the 'rows' variable for a bit to store the escaped
467
mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table));
468
snprintf(query, sizeof(query), "show%s tables like '%s'",
469
opt_table_type ? " full" : "", rows);
472
snprintf(query, sizeof(query), "show%s tables",
473
opt_table_type ? " full" : "");
474
if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql)))
476
fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db,
480
printf("Database: %s",db);
482
printf(" Wildcard: %s",table);
486
head_length=(uint) strlen(header);
487
field=mysql_fetch_field(result);
488
if (head_length < field->max_length)
489
head_length=field->max_length;
494
print_header(header,head_length,"table_type",10,NullS);
495
else if (opt_verbose == 1)
496
print_header(header,head_length,"table_type",10,"Columns",8,NullS);
499
print_header(header,head_length,"table_type",10,"Columns",8,
500
"Total Rows",10,NullS);
506
print_header(header,head_length,NullS);
507
else if (opt_verbose == 1)
508
print_header(header,head_length,"Columns",8,NullS);
510
print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
513
while ((row = mysql_fetch_row(result)))
518
if (!(mysql_select_db(mysql,db)))
520
MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL);
524
strmov(fields,"N/A");
529
sprintf(fields,"%8u",(uint) mysql_num_fields(rresult));
530
mysql_free_result(rresult);
534
/* Print the count of rows for each table */
535
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
536
if (!(mysql_query(mysql,query)))
538
if ((rresult = mysql_store_result(mysql)))
540
rrow = mysql_fetch_row(rresult);
541
rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10);
542
mysql_free_result(rresult);
544
sprintf(rows,"%10lu",rowcount);
547
sprintf(rows,"%10d",0);
553
strmov(fields,"N/A");
560
print_row(row[0],head_length,row[1],10,NullS);
561
else if (opt_verbose == 1)
562
print_row(row[0],head_length,row[1],10,fields,8,NullS);
564
print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS);
569
print_row(row[0],head_length,NullS);
570
else if (opt_verbose == 1)
571
print_row(row[0],head_length, fields,8, NullS);
573
print_row(row[0],head_length, fields,8, rows,10, NullS);
577
print_trailer(head_length,
578
(opt_table_type ? 10 : opt_verbose > 0 ? 8 : 0),
579
(opt_table_type ? (opt_verbose > 0 ? 8 : 0)
580
: (opt_verbose > 1 ? 10 :0)),
581
!opt_table_type ? 0 : opt_verbose > 1 ? 10 :0,
584
if (counter && opt_verbose)
585
printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : "");
587
mysql_free_result(result);
593
list_table_status(MYSQL *mysql,const char *db,const char *wild)
595
char query[1024],*end;
599
end=strxmov(query,"show table status from `",db,"`",NullS);
601
strxmov(end," like '",wild,"'",NullS);
602
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
604
fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n",
605
my_progname,db,wild ? wild : "",mysql_error(mysql));
606
if (mysql_errno(mysql) == ER_PARSE_ERROR)
607
fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n");
611
printf("Database: %s",db);
613
printf(" Wildcard: %s",wild);
616
print_res_header(result);
617
while ((row=mysql_fetch_row(result)))
618
print_res_row(result,row);
619
print_res_top(result);
620
mysql_free_result(result);
625
list fields uses field interface as an example of how to parse
630
list_fields(MYSQL *mysql,const char *db,const char *table,
633
char query[1024],*end;
638
if (mysql_select_db(mysql,db))
640
fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db,
647
sprintf(query,"select count(*) from `%s`", table);
648
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
650
fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
651
my_progname,db,table,mysql_error(mysql));
654
row= mysql_fetch_row(result);
655
rows= (ulong) strtoull(row[0], (char**) 0, 10);
656
mysql_free_result(result);
659
end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
661
strxmov(end," like '",wild,"'",NullS);
662
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
664
fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n",
665
my_progname,db,table,mysql_error(mysql));
669
printf("Database: %s Table: %s", db, table);
671
printf(" Rows: %lu", rows);
673
printf(" Wildcard: %s",wild);
676
print_res_header(result);
677
while ((row=mysql_fetch_row(result)))
678
print_res_row(result,row);
679
print_res_top(result);
682
end=strmov(strmov(strmov(query,"show keys from `"),table),"`");
683
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
685
fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n",
686
my_progname,db,table,mysql_error(mysql));
689
if (mysql_num_rows(result))
691
print_res_header(result);
692
while ((row=mysql_fetch_row(result)))
693
print_res_row(result,row);
694
print_res_top(result);
697
puts("Table has no keys");
699
mysql_free_result(result);
704
/*****************************************************************************
705
General functions to print a nice ascii-table from data
706
*****************************************************************************/
709
print_header(const char *header,uint head_length,...)
712
uint length,i,str_length,pre_space;
715
va_start(args,head_length);
717
field=header; length=head_length;
720
for (i=0 ; i < length+2 ; i++)
723
if (!(field=va_arg(args,char *)))
725
length=va_arg(args,uint);
730
va_start(args,head_length);
731
field=header; length=head_length;
735
str_length=(uint) strlen(field);
736
if (str_length > length)
738
pre_space=(uint) (((int) length-(int) str_length)/2)+1;
739
for (i=0 ; i < pre_space ; i++)
741
for (i = 0 ; i < str_length ; i++)
743
length=length+2-str_length-pre_space;
744
for (i=0 ; i < length ; i++)
747
if (!(field=va_arg(args,char *)))
749
length=va_arg(args,uint);
754
va_start(args,head_length);
756
field=header; length=head_length;
759
for (i=0 ; i < length+2 ; i++)
762
if (!(field=va_arg(args,char *)))
764
length=va_arg(args,uint);
772
print_row(const char *header,uint head_length,...)
776
uint i,length,field_length;
778
va_start(args,head_length);
779
field=header; length=head_length;
785
field_length=(uint) strlen(field);
786
for (i=field_length ; i <= length ; i++)
788
if (!(field=va_arg(args,char *)))
790
length=va_arg(args,uint);
799
print_trailer(uint head_length,...)
804
va_start(args,head_length);
809
for (i=0 ; i < length+2 ; i++)
812
if (!(length=va_arg(args,uint)))
820
static void print_res_header(MYSQL_RES *result)
824
print_res_top(result);
825
mysql_field_seek(result,0);
827
while ((field = mysql_fetch_field(result)))
829
printf(" %-*s|",(int) field->max_length+1,field->name);
832
print_res_top(result);
836
static void print_res_top(MYSQL_RES *result)
842
mysql_field_seek(result,0);
843
while((field = mysql_fetch_field(result)))
845
if ((length=(uint) strlen(field->name)) > field->max_length)
846
field->max_length=length;
848
length=field->max_length;
849
for (i=length+2 ; i--> 0 ; )
857
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur)
862
mysql_field_seek(result,0);
863
for (i=0 ; i < mysql_num_fields(result); i++)
865
field = mysql_fetch_field(result);
866
length=field->max_length;
867
printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");