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[] =
162
{"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
163
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
165
{"character-sets-dir", 'c', "Directory where character sets are.",
166
(uchar**) &charsets_dir, (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
168
{"default-character-set", OPT_DEFAULT_CHARSET,
169
"Set the default character set.", (uchar**) &default_charset,
170
(uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
172
"Show number of rows per table (may be slow for not MyISAM tables)",
173
(uchar**) &opt_count, (uchar**) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
175
{"compress", 'C', "Use compression in server/client protocol.",
176
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
178
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
179
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
180
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
181
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
182
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
183
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
184
(uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
185
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
186
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
188
{"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR,
189
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
190
{"status", 'i', "Shows a lot of extra information about each table.",
191
(uchar**) &opt_status, (uchar**) &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
193
{"keys", 'k', "Show keys for table.", (uchar**) &opt_show_keys,
194
(uchar**) &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
196
"Password to use when connecting to server. If password is not given it's asked from the tty.",
197
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
198
{"port", 'P', "Port number to use for connection or 0 for default to, in "
199
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
200
#if MYSQL_PORT_DEFAULT == 0
203
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
204
(uchar**) &opt_mysql_port,
205
(uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
208
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
209
NO_ARG, 0, 0, 0, 0, 0, 0},
211
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
212
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
214
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
215
"Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
216
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
218
{"show-table-type", 't', "Show table type column.",
219
(uchar**) &opt_table_type, (uchar**) &opt_table_type, 0, GET_BOOL,
220
NO_ARG, 0, 0, 0, 0, 0, 0},
221
{"socket", 'S', "Socket file to use for connection.",
222
(uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
223
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
224
#ifndef DONT_ALLOW_USER_CHANGE
225
{"user", 'u', "User for login if not current user.", (uchar**) &user,
226
(uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
229
"More verbose output; You can use this multiple times to get even more verbose output.",
230
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
231
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
232
NO_ARG, 0, 0, 0, 0, 0, 0},
233
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
237
#include <help_start.h>
239
static void print_version(void)
241
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
242
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
243
NETWARE_SET_SCREEN_MODE(1);
247
static void usage(void)
250
puts("Copyright (C) 2000-2006 MySQL AB");
251
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");
252
puts("Shows the structure of a mysql database (databases,tables and columns)\n");
253
printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
255
If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\
256
what\'s matched by the wildcard is shown.\n\
257
If no database is given then all matching databases are shown.\n\
258
If no table is given then all matching tables in database are shown\n\
259
If no column is given then all matching columns and columntypes in table\n\
261
print_defaults("my",load_default_groups);
262
my_print_help(my_long_options);
263
my_print_variables(my_long_options);
266
#include <help_end.h>
269
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
275
setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
284
char *start=argument;
285
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
286
opt_password=my_strdup(argument,MYF(MY_FAE));
287
while (*argument) *argument++= 'x'; /* Destroy argument */
289
start[1]=0; /* Cut length of argument */
295
case OPT_MYSQL_PROTOCOL:
296
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
300
DBUG_PUSH(argument ? argument : "d:t:o");
317
get_options(int *argc,char ***argv)
321
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
325
opt_password=get_tty_password(NullS);
329
We need to set verbose to 2 as we need to change the output to include
330
the number-of-rows column
335
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
336
if (debug_check_flag)
337
my_end_arg= MY_CHECK_ERROR;
343
list_dbs(MYSQL *mysql,const char *wild)
346
uint length, counter = 0;
348
char tables[NAME_LEN+1], rows[NAME_LEN+1];
352
MYSQL_ROW row= NULL, rrow;
354
if (!(result=mysql_list_dbs(mysql,wild)))
356
fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname,
362
If a wildcard was used, but there was only one row and it's name is an
363
exact match, we'll assume they really wanted to see the contents of that
364
database. This is because it is fairly common for database names to
365
contain the underscore (_), like INFORMATION_SCHEMA.
367
if (wild && mysql_num_rows(result) == 1)
369
row= mysql_fetch_row(result);
370
if (!my_strcasecmp(&my_charset_latin1, row[0], wild))
372
mysql_free_result(result);
374
return list_table_status(mysql, wild, NULL);
376
return list_tables(mysql, wild, NULL);
381
printf("Wildcard: %s\n",wild);
384
length=(uint) strlen(header);
385
field=mysql_fetch_field(result);
386
if (length < field->max_length)
387
length=field->max_length;
390
print_header(header,length,NullS);
391
else if (opt_verbose == 1)
392
print_header(header,length,"Tables",6,NullS);
394
print_header(header,length,"Tables",6,"Total Rows",12,NullS);
396
/* The first row may have already been read up above. */
397
while (row || (row= mysql_fetch_row(result)))
403
if (!(mysql_select_db(mysql,row[0])))
405
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
406
if (mysql_affected_rows(mysql) > 0)
408
sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql));
412
/* Print the count of tables and rows for each database */
414
while ((trow = mysql_fetch_row(tresult)))
416
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
417
if (!(mysql_query(mysql,query)))
420
if ((rresult = mysql_store_result(mysql)))
422
rrow = mysql_fetch_row(rresult);
423
rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10);
424
mysql_free_result(rresult);
428
sprintf(rows,"%12lu",rowcount);
433
sprintf(tables,"%6d",0);
434
sprintf(rows,"%12d",0);
436
mysql_free_result(tresult);
440
strmov(tables,"N/A");
446
print_row(row[0],length,0);
447
else if (opt_verbose == 1)
448
print_row(row[0],length,tables,6,NullS);
450
print_row(row[0],length,tables,6,rows,12,NullS);
455
print_trailer(length,
456
(opt_verbose > 0 ? 6 : 0),
457
(opt_verbose > 1 ? 12 :0),
460
if (counter && opt_verbose)
461
printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : "");
462
mysql_free_result(result);
468
list_tables(MYSQL *mysql,const char *db,const char *table)
471
uint head_length, counter = 0;
472
char query[255], rows[NAME_LEN], fields[16];
477
if (mysql_select_db(mysql,db))
479
fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db,
486
We just hijack the 'rows' variable for a bit to store the escaped
489
mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table));
490
my_snprintf(query, sizeof(query), "show%s tables like '%s'",
491
opt_table_type ? " full" : "", rows);
494
my_snprintf(query, sizeof(query), "show%s tables",
495
opt_table_type ? " full" : "");
496
if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql)))
498
fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db,
502
printf("Database: %s",db);
504
printf(" Wildcard: %s",table);
508
head_length=(uint) strlen(header);
509
field=mysql_fetch_field(result);
510
if (head_length < field->max_length)
511
head_length=field->max_length;
516
print_header(header,head_length,"table_type",10,NullS);
517
else if (opt_verbose == 1)
518
print_header(header,head_length,"table_type",10,"Columns",8,NullS);
521
print_header(header,head_length,"table_type",10,"Columns",8,
522
"Total Rows",10,NullS);
528
print_header(header,head_length,NullS);
529
else if (opt_verbose == 1)
530
print_header(header,head_length,"Columns",8,NullS);
532
print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
535
while ((row = mysql_fetch_row(result)))
540
if (!(mysql_select_db(mysql,db)))
542
MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL);
546
strmov(fields,"N/A");
551
sprintf(fields,"%8u",(uint) mysql_num_fields(rresult));
552
mysql_free_result(rresult);
556
/* Print the count of rows for each table */
557
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
558
if (!(mysql_query(mysql,query)))
560
if ((rresult = mysql_store_result(mysql)))
562
rrow = mysql_fetch_row(rresult);
563
rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10);
564
mysql_free_result(rresult);
566
sprintf(rows,"%10lu",rowcount);
569
sprintf(rows,"%10d",0);
575
strmov(fields,"N/A");
582
print_row(row[0],head_length,row[1],10,NullS);
583
else if (opt_verbose == 1)
584
print_row(row[0],head_length,row[1],10,fields,8,NullS);
586
print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS);
591
print_row(row[0],head_length,NullS);
592
else if (opt_verbose == 1)
593
print_row(row[0],head_length, fields,8, NullS);
595
print_row(row[0],head_length, fields,8, rows,10, NullS);
599
print_trailer(head_length,
600
(opt_table_type ? 10 : opt_verbose > 0 ? 8 : 0),
601
(opt_table_type ? (opt_verbose > 0 ? 8 : 0)
602
: (opt_verbose > 1 ? 10 :0)),
603
!opt_table_type ? 0 : opt_verbose > 1 ? 10 :0,
606
if (counter && opt_verbose)
607
printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : "");
609
mysql_free_result(result);
615
list_table_status(MYSQL *mysql,const char *db,const char *wild)
617
char query[1024],*end;
621
end=strxmov(query,"show table status from `",db,"`",NullS);
623
strxmov(end," like '",wild,"'",NullS);
624
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
626
fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n",
627
my_progname,db,wild ? wild : "",mysql_error(mysql));
628
if (mysql_errno(mysql) == ER_PARSE_ERROR)
629
fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n");
633
printf("Database: %s",db);
635
printf(" Wildcard: %s",wild);
638
print_res_header(result);
639
while ((row=mysql_fetch_row(result)))
640
print_res_row(result,row);
641
print_res_top(result);
642
mysql_free_result(result);
647
list fields uses field interface as an example of how to parse
652
list_fields(MYSQL *mysql,const char *db,const char *table,
655
char query[1024],*end;
660
if (mysql_select_db(mysql,db))
662
fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db,
669
sprintf(query,"select count(*) from `%s`", table);
670
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
672
fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
673
my_progname,db,table,mysql_error(mysql));
676
row= mysql_fetch_row(result);
677
rows= (ulong) strtoull(row[0], (char**) 0, 10);
678
mysql_free_result(result);
681
end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
683
strxmov(end," like '",wild,"'",NullS);
684
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
686
fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n",
687
my_progname,db,table,mysql_error(mysql));
691
printf("Database: %s Table: %s", db, table);
693
printf(" Rows: %lu", rows);
695
printf(" Wildcard: %s",wild);
698
print_res_header(result);
699
while ((row=mysql_fetch_row(result)))
700
print_res_row(result,row);
701
print_res_top(result);
704
end=strmov(strmov(strmov(query,"show keys from `"),table),"`");
705
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
707
fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n",
708
my_progname,db,table,mysql_error(mysql));
711
if (mysql_num_rows(result))
713
print_res_header(result);
714
while ((row=mysql_fetch_row(result)))
715
print_res_row(result,row);
716
print_res_top(result);
719
puts("Table has no keys");
721
mysql_free_result(result);
726
/*****************************************************************************
727
General functions to print a nice ascii-table from data
728
*****************************************************************************/
731
print_header(const char *header,uint head_length,...)
734
uint length,i,str_length,pre_space;
737
va_start(args,head_length);
739
field=header; length=head_length;
742
for (i=0 ; i < length+2 ; i++)
745
if (!(field=va_arg(args,char *)))
747
length=va_arg(args,uint);
752
va_start(args,head_length);
753
field=header; length=head_length;
757
str_length=(uint) strlen(field);
758
if (str_length > length)
760
pre_space=(uint) (((int) length-(int) str_length)/2)+1;
761
for (i=0 ; i < pre_space ; i++)
763
for (i = 0 ; i < str_length ; i++)
765
length=length+2-str_length-pre_space;
766
for (i=0 ; i < length ; i++)
769
if (!(field=va_arg(args,char *)))
771
length=va_arg(args,uint);
776
va_start(args,head_length);
778
field=header; length=head_length;
781
for (i=0 ; i < length+2 ; i++)
784
if (!(field=va_arg(args,char *)))
786
length=va_arg(args,uint);
794
print_row(const char *header,uint head_length,...)
798
uint i,length,field_length;
800
va_start(args,head_length);
801
field=header; length=head_length;
807
field_length=(uint) strlen(field);
808
for (i=field_length ; i <= length ; i++)
810
if (!(field=va_arg(args,char *)))
812
length=va_arg(args,uint);
821
print_trailer(uint head_length,...)
826
va_start(args,head_length);
831
for (i=0 ; i < length+2 ; i++)
834
if (!(length=va_arg(args,uint)))
842
static void print_res_header(MYSQL_RES *result)
846
print_res_top(result);
847
mysql_field_seek(result,0);
849
while ((field = mysql_fetch_field(result)))
851
printf(" %-*s|",(int) field->max_length+1,field->name);
854
print_res_top(result);
858
static void print_res_top(MYSQL_RES *result)
864
mysql_field_seek(result,0);
865
while((field = mysql_fetch_field(result)))
867
if ((length=(uint) strlen(field->name)) > field->max_length)
868
field->max_length=length;
870
length=field->max_length;
871
for (i=length+2 ; i--> 0 ; )
879
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur)
884
mysql_field_seek(result,0);
885
for (i=0 ; i < mysql_num_fields(result); i++)
887
field = mysql_fetch_field(result);
888
length=field->max_length;
889
printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");