1
by brian
clean slate |
1 |
/* Copyright (C) 2000-2006 MySQL AB
|
2 |
||
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.
|
|
6 |
||
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.
|
|
11 |
||
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 */
|
|
15 |
||
16 |
/* Show databases, tables or columns */
|
|
17 |
||
18 |
#define SHOW_VERSION "9.10"
|
|
19 |
||
20 |
#include "client_priv.h" |
|
21 |
#include <my_sys.h> |
|
22 |
#include <m_string.h> |
|
23 |
#include <mysqld_error.h> |
|
24 |
#include <signal.h> |
|
25 |
#include <stdarg.h> |
|
26 |
||
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; |
|
34 |
||
35 |
#ifdef HAVE_SMEM
|
|
36 |
static char *shared_memory_base_name=0; |
|
37 |
#endif
|
|
38 |
static uint opt_protocol=0; |
|
39 |
||
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, |
|
46 |
const char *field); |
|
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); |
|
53 |
||
54 |
static const char *load_default_groups[]= { "mysqlshow","client",0 }; |
|
55 |
static char * opt_mysql_unix_port=0; |
|
56 |
||
57 |
int main(int argc, char **argv) |
|
58 |
{
|
|
59 |
int error; |
|
60 |
my_bool first_argument_uses_wildcards=0; |
|
61 |
char *wild; |
|
62 |
MYSQL mysql; |
|
63 |
MY_INIT(argv[0]); |
|
64 |
load_defaults("my",load_default_groups,&argc,&argv); |
|
65 |
get_options(&argc,&argv); |
|
66 |
||
67 |
wild=0; |
|
68 |
if (argc) |
|
69 |
{
|
|
70 |
char *pos= argv[argc-1], *to; |
|
71 |
for (to= pos ; *pos ; pos++, to++) |
|
72 |
{
|
|
73 |
switch (*pos) { |
|
74 |
case '*': |
|
75 |
*pos= '%'; |
|
76 |
first_argument_uses_wildcards= 1; |
|
77 |
break; |
|
78 |
case '?': |
|
79 |
*pos= '_'; |
|
80 |
first_argument_uses_wildcards= 1; |
|
81 |
break; |
|
82 |
case '%': |
|
83 |
case '_': |
|
84 |
first_argument_uses_wildcards= 1; |
|
85 |
break; |
|
86 |
case '\\': |
|
87 |
pos++; |
|
88 |
default: break; |
|
89 |
}
|
|
90 |
*to= *pos; |
|
91 |
}
|
|
92 |
*to= *pos; /* just to copy a '\0' if '\\' was used */ |
|
93 |
}
|
|
94 |
if (first_argument_uses_wildcards) |
|
95 |
wild= argv[--argc]; |
|
96 |
else if (argc == 3) /* We only want one field */ |
|
97 |
wild= argv[--argc]; |
|
98 |
||
99 |
if (argc > 2) |
|
100 |
{
|
|
101 |
fprintf(stderr,"%s: Too many arguments\n",my_progname); |
|
102 |
exit(1); |
|
103 |
}
|
|
104 |
mysql_init(&mysql); |
|
105 |
if (opt_compress) |
|
106 |
mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); |
|
107 |
if (opt_protocol) |
|
108 |
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); |
|
109 |
#ifdef HAVE_SMEM
|
|
110 |
if (shared_memory_base_name) |
|
111 |
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); |
|
112 |
#endif
|
|
113 |
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); |
|
114 |
||
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, |
|
118 |
0))) |
|
119 |
{
|
|
120 |
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql)); |
|
121 |
exit(1); |
|
122 |
}
|
|
123 |
mysql.reconnect= 1; |
|
124 |
||
125 |
switch (argc) { |
|
126 |
case 0: error=list_dbs(&mysql,wild); break; |
|
127 |
case 1: |
|
128 |
if (opt_status) |
|
129 |
error=list_table_status(&mysql,argv[0],wild); |
|
130 |
else
|
|
131 |
error=list_tables(&mysql,argv[0],wild); |
|
132 |
break; |
|
133 |
default: |
|
134 |
if (opt_status && ! wild) |
|
135 |
error=list_table_status(&mysql,argv[0],argv[1]); |
|
136 |
else
|
|
137 |
error=list_fields(&mysql,argv[0],argv[1],wild); |
|
138 |
break; |
|
139 |
}
|
|
140 |
mysql_close(&mysql); /* Close & free connection */ |
|
141 |
if (opt_password) |
|
142 |
my_free(opt_password,MYF(0)); |
|
143 |
#ifdef HAVE_SMEM
|
|
144 |
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); |
|
145 |
#endif
|
|
146 |
my_end(my_end_arg); |
|
147 |
exit(error ? 1 : 0); |
|
148 |
}
|
|
149 |
||
150 |
static struct my_option my_long_options[] = |
|
151 |
{
|
|
152 |
{"character-sets-dir", 'c', "Directory where character sets are.", |
|
153 |
(uchar**) &charsets_dir, (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, |
|
154 |
0, 0, 0, 0, 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}, |
|
158 |
{"count", OPT_COUNT, |
|
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, |
|
161 |
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, |
|
164 |
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, |
|
174 |
0, 0, 0, 0, 0, 0}, |
|
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, |
|
179 |
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}, |
|
182 |
{"password", 'p', |
|
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
|
|
188 |
"/etc/services, "
|
|
189 |
#endif
|
|
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, |
|
193 |
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}, |
|
196 |
#ifdef HAVE_SMEM
|
|
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}, |
|
200 |
#endif
|
|
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}, |
|
210 |
#endif
|
|
211 |
{"verbose", 'v', |
|
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} |
|
217 |
};
|
|
218 |
||
219 |
||
220 |
#include <help_start.h> |
|
221 |
||
222 |
static void print_version(void) |
|
223 |
{
|
|
224 |
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION, |
|
225 |
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); |
|
226 |
}
|
|
227 |
||
228 |
||
229 |
static void usage(void) |
|
230 |
{
|
|
231 |
print_version(); |
|
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); |
|
236 |
puts("\n\ |
|
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\ |
|
242 |
are shown"); |
|
243 |
print_defaults("my",load_default_groups); |
|
244 |
my_print_help(my_long_options); |
|
245 |
my_print_variables(my_long_options); |
|
246 |
}
|
|
247 |
||
248 |
#include <help_end.h> |
|
249 |
||
250 |
static my_bool |
|
251 |
get_one_option(int optid, const struct my_option *opt __attribute__((unused)), |
|
252 |
char *argument) |
|
253 |
{
|
|
254 |
switch(optid) { |
|
255 |
case 'v': |
|
256 |
opt_verbose++; |
|
257 |
break; |
|
258 |
case 'p': |
|
259 |
if (argument) |
|
260 |
{
|
|
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 */ |
|
265 |
if (*start) |
|
266 |
start[1]=0; /* Cut length of argument */ |
|
267 |
tty_password= 0; |
|
268 |
}
|
|
269 |
else
|
|
270 |
tty_password=1; |
|
271 |
break; |
|
272 |
case OPT_MYSQL_PROTOCOL: |
|
273 |
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, |
|
274 |
opt->name); |
|
275 |
break; |
|
276 |
case '#': |
|
277 |
DBUG_PUSH(argument ? argument : "d:t:o"); |
|
278 |
debug_check_flag= 1; |
|
279 |
break; |
|
280 |
case 'V': |
|
281 |
print_version(); |
|
282 |
exit(0); |
|
283 |
break; |
|
284 |
case '?': |
|
285 |
case 'I': /* Info */ |
|
286 |
usage(); |
|
287 |
exit(0); |
|
288 |
}
|
|
289 |
return 0; |
|
290 |
}
|
|
291 |
||
292 |
||
293 |
static void |
|
294 |
get_options(int *argc,char ***argv) |
|
295 |
{
|
|
296 |
int ho_error; |
|
297 |
||
298 |
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) |
|
299 |
exit(ho_error); |
|
300 |
||
301 |
if (tty_password) |
|
302 |
opt_password=get_tty_password(NullS); |
|
303 |
if (opt_count) |
|
304 |
{
|
|
305 |
/*
|
|
306 |
We need to set verbose to 2 as we need to change the output to include
|
|
307 |
the number-of-rows column
|
|
308 |
*/
|
|
309 |
opt_verbose= 2; |
|
310 |
}
|
|
311 |
if (debug_info_flag) |
|
312 |
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO; |
|
313 |
if (debug_check_flag) |
|
314 |
my_end_arg= MY_CHECK_ERROR; |
|
315 |
return; |
|
316 |
}
|
|
317 |
||
318 |
||
319 |
static int |
|
320 |
list_dbs(MYSQL *mysql,const char *wild) |
|
321 |
{
|
|
322 |
const char *header; |
|
323 |
uint length, counter = 0; |
|
324 |
ulong rowcount = 0L; |
|
325 |
char tables[NAME_LEN+1], rows[NAME_LEN+1]; |
|
326 |
char query[255]; |
|
327 |
MYSQL_FIELD *field; |
|
328 |
MYSQL_RES *result; |
|
329 |
MYSQL_ROW row= NULL, rrow; |
|
330 |
||
331 |
if (!(result=mysql_list_dbs(mysql,wild))) |
|
332 |
{
|
|
333 |
fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname, |
|
334 |
mysql_error(mysql)); |
|
335 |
return 1; |
|
336 |
}
|
|
337 |
||
338 |
/*
|
|
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.
|
|
343 |
*/
|
|
344 |
if (wild && mysql_num_rows(result) == 1) |
|
345 |
{
|
|
346 |
row= mysql_fetch_row(result); |
|
347 |
if (!my_strcasecmp(&my_charset_latin1, row[0], wild)) |
|
348 |
{
|
|
349 |
mysql_free_result(result); |
|
350 |
if (opt_status) |
|
351 |
return list_table_status(mysql, wild, NULL); |
|
352 |
else
|
|
353 |
return list_tables(mysql, wild, NULL); |
|
354 |
}
|
|
355 |
}
|
|
356 |
||
357 |
if (wild) |
|
358 |
printf("Wildcard: %s\n",wild); |
|
359 |
||
360 |
header="Databases"; |
|
361 |
length=(uint) strlen(header); |
|
362 |
field=mysql_fetch_field(result); |
|
363 |
if (length < field->max_length) |
|
364 |
length=field->max_length; |
|
365 |
||
366 |
if (!opt_verbose) |
|
367 |
print_header(header,length,NullS); |
|
368 |
else if (opt_verbose == 1) |
|
369 |
print_header(header,length,"Tables",6,NullS); |
|
370 |
else
|
|
371 |
print_header(header,length,"Tables",6,"Total Rows",12,NullS); |
|
372 |
||
373 |
/* The first row may have already been read up above. */
|
|
374 |
while (row || (row= mysql_fetch_row(result))) |
|
375 |
{
|
|
376 |
counter++; |
|
377 |
||
378 |
if (opt_verbose) |
|
379 |
{
|
|
380 |
if (!(mysql_select_db(mysql,row[0]))) |
|
381 |
{
|
|
382 |
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL); |
|
383 |
if (mysql_affected_rows(mysql) > 0) |
|
384 |
{
|
|
385 |
sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql)); |
|
386 |
rowcount = 0; |
|
387 |
if (opt_verbose > 1) |
|
388 |
{
|
|
389 |
/* Print the count of tables and rows for each database */
|
|
390 |
MYSQL_ROW trow; |
|
391 |
while ((trow = mysql_fetch_row(tresult))) |
|
392 |
{
|
|
393 |
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]); |
|
394 |
if (!(mysql_query(mysql,query))) |
|
395 |
{
|
|
396 |
MYSQL_RES *rresult; |
|
397 |
if ((rresult = mysql_store_result(mysql))) |
|
398 |
{
|
|
399 |
rrow = mysql_fetch_row(rresult); |
|
400 |
rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10); |
|
401 |
mysql_free_result(rresult); |
|
402 |
}
|
|
403 |
}
|
|
404 |
}
|
|
405 |
sprintf(rows,"%12lu",rowcount); |
|
406 |
}
|
|
407 |
}
|
|
408 |
else
|
|
409 |
{
|
|
410 |
sprintf(tables,"%6d",0); |
|
411 |
sprintf(rows,"%12d",0); |
|
412 |
}
|
|
413 |
mysql_free_result(tresult); |
|
414 |
}
|
|
415 |
else
|
|
416 |
{
|
|
417 |
strmov(tables,"N/A"); |
|
418 |
strmov(rows,"N/A"); |
|
419 |
}
|
|
420 |
}
|
|
421 |
||
422 |
if (!opt_verbose) |
|
423 |
print_row(row[0],length,0); |
|
424 |
else if (opt_verbose == 1) |
|
425 |
print_row(row[0],length,tables,6,NullS); |
|
426 |
else
|
|
427 |
print_row(row[0],length,tables,6,rows,12,NullS); |
|
428 |
||
429 |
row= NULL; |
|
430 |
}
|
|
431 |
||
432 |
print_trailer(length, |
|
433 |
(opt_verbose > 0 ? 6 : 0), |
|
434 |
(opt_verbose > 1 ? 12 :0), |
|
435 |
0); |
|
436 |
||
437 |
if (counter && opt_verbose) |
|
438 |
printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : ""); |
|
439 |
mysql_free_result(result); |
|
440 |
return 0; |
|
441 |
}
|
|
442 |
||
443 |
||
444 |
static int |
|
445 |
list_tables(MYSQL *mysql,const char *db,const char *table) |
|
446 |
{
|
|
447 |
const char *header; |
|
448 |
uint head_length, counter = 0; |
|
449 |
char query[255], rows[NAME_LEN], fields[16]; |
|
450 |
MYSQL_FIELD *field; |
|
451 |
MYSQL_RES *result; |
|
452 |
MYSQL_ROW row, rrow; |
|
453 |
||
454 |
if (mysql_select_db(mysql,db)) |
|
455 |
{
|
|
456 |
fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db, |
|
457 |
mysql_error(mysql)); |
|
458 |
return 1; |
|
459 |
}
|
|
460 |
if (table) |
|
461 |
{
|
|
462 |
/*
|
|
463 |
We just hijack the 'rows' variable for a bit to store the escaped
|
|
464 |
table name
|
|
465 |
*/
|
|
466 |
mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table)); |
|
77.1.18
by Monty Taylor
Removed my_vsnprintf and my_snprintf. |
467 |
snprintf(query, sizeof(query), "show%s tables like '%s'", |
468 |
opt_table_type ? " full" : "", rows); |
|
1
by brian
clean slate |
469 |
}
|
470 |
else
|
|
77.1.18
by Monty Taylor
Removed my_vsnprintf and my_snprintf. |
471 |
snprintf(query, sizeof(query), "show%s tables", |
472 |
opt_table_type ? " full" : ""); |
|
1
by brian
clean slate |
473 |
if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql))) |
474 |
{
|
|
475 |
fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db, |
|
476 |
mysql_error(mysql)); |
|
477 |
exit(1); |
|
478 |
}
|
|
479 |
printf("Database: %s",db); |
|
480 |
if (table) |
|
481 |
printf(" Wildcard: %s",table); |
|
482 |
putchar('\n'); |
|
483 |
||
484 |
header="Tables"; |
|
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; |
|
489 |
||
490 |
if (opt_table_type) |
|
491 |
{
|
|
492 |
if (!opt_verbose) |
|
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); |
|
496 |
else
|
|
497 |
{
|
|
498 |
print_header(header,head_length,"table_type",10,"Columns",8, |
|
499 |
"Total Rows",10,NullS); |
|
500 |
}
|
|
501 |
}
|
|
502 |
else
|
|
503 |
{
|
|
504 |
if (!opt_verbose) |
|
505 |
print_header(header,head_length,NullS); |
|
506 |
else if (opt_verbose == 1) |
|
507 |
print_header(header,head_length,"Columns",8,NullS); |
|
508 |
else
|
|
509 |
print_header(header,head_length,"Columns",8, "Total Rows",10,NullS); |
|
510 |
}
|
|
511 |
||
512 |
while ((row = mysql_fetch_row(result))) |
|
513 |
{
|
|
514 |
counter++; |
|
515 |
if (opt_verbose > 0) |
|
516 |
{
|
|
517 |
if (!(mysql_select_db(mysql,db))) |
|
518 |
{
|
|
519 |
MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL); |
|
520 |
ulong rowcount=0L; |
|
521 |
if (!rresult) |
|
522 |
{
|
|
523 |
strmov(fields,"N/A"); |
|
524 |
strmov(rows,"N/A"); |
|
525 |
}
|
|
526 |
else
|
|
527 |
{
|
|
528 |
sprintf(fields,"%8u",(uint) mysql_num_fields(rresult)); |
|
529 |
mysql_free_result(rresult); |
|
530 |
||
531 |
if (opt_verbose > 1) |
|
532 |
{
|
|
533 |
/* Print the count of rows for each table */
|
|
534 |
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]); |
|
535 |
if (!(mysql_query(mysql,query))) |
|
536 |
{
|
|
537 |
if ((rresult = mysql_store_result(mysql))) |
|
538 |
{
|
|
539 |
rrow = mysql_fetch_row(rresult); |
|
540 |
rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10); |
|
541 |
mysql_free_result(rresult); |
|
542 |
}
|
|
543 |
sprintf(rows,"%10lu",rowcount); |
|
544 |
}
|
|
545 |
else
|
|
546 |
sprintf(rows,"%10d",0); |
|
547 |
}
|
|
548 |
}
|
|
549 |
}
|
|
550 |
else
|
|
551 |
{
|
|
552 |
strmov(fields,"N/A"); |
|
553 |
strmov(rows,"N/A"); |
|
554 |
}
|
|
555 |
}
|
|
556 |
if (opt_table_type) |
|
557 |
{
|
|
558 |
if (!opt_verbose) |
|
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); |
|
562 |
else
|
|
563 |
print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS); |
|
564 |
}
|
|
565 |
else
|
|
566 |
{
|
|
567 |
if (!opt_verbose) |
|
568 |
print_row(row[0],head_length,NullS); |
|
569 |
else if (opt_verbose == 1) |
|
570 |
print_row(row[0],head_length, fields,8, NullS); |
|
571 |
else
|
|
572 |
print_row(row[0],head_length, fields,8, rows,10, NullS); |
|
573 |
}
|
|
574 |
}
|
|
575 |
||
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, |
|
581 |
0); |
|
582 |
||
583 |
if (counter && opt_verbose) |
|
584 |
printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : ""); |
|
585 |
||
586 |
mysql_free_result(result); |
|
587 |
return 0; |
|
588 |
}
|
|
589 |
||
590 |
||
591 |
static int |
|
592 |
list_table_status(MYSQL *mysql,const char *db,const char *wild) |
|
593 |
{
|
|
594 |
char query[1024],*end; |
|
595 |
MYSQL_RES *result; |
|
596 |
MYSQL_ROW row; |
|
597 |
||
598 |
end=strxmov(query,"show table status from `",db,"`",NullS); |
|
599 |
if (wild && wild[0]) |
|
600 |
strxmov(end," like '",wild,"'",NullS); |
|
601 |
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) |
|
602 |
{
|
|
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"); |
|
607 |
return 1; |
|
608 |
}
|
|
609 |
||
610 |
printf("Database: %s",db); |
|
611 |
if (wild) |
|
612 |
printf(" Wildcard: %s",wild); |
|
613 |
putchar('\n'); |
|
614 |
||
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); |
|
620 |
return 0; |
|
621 |
}
|
|
622 |
||
623 |
/*
|
|
624 |
list fields uses field interface as an example of how to parse
|
|
625 |
a MYSQL FIELD
|
|
626 |
*/
|
|
627 |
||
628 |
static int |
|
629 |
list_fields(MYSQL *mysql,const char *db,const char *table, |
|
630 |
const char *wild) |
|
631 |
{
|
|
632 |
char query[1024],*end; |
|
633 |
MYSQL_RES *result; |
|
634 |
MYSQL_ROW row; |
|
635 |
ulong rows= 0; |
|
636 |
||
637 |
if (mysql_select_db(mysql,db)) |
|
638 |
{
|
|
639 |
fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db, |
|
640 |
mysql_error(mysql)); |
|
641 |
return 1; |
|
642 |
}
|
|
643 |
||
644 |
if (opt_count) |
|
645 |
{
|
|
646 |
sprintf(query,"select count(*) from `%s`", table); |
|
647 |
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) |
|
648 |
{
|
|
649 |
fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n", |
|
650 |
my_progname,db,table,mysql_error(mysql)); |
|
651 |
return 1; |
|
652 |
}
|
|
653 |
row= mysql_fetch_row(result); |
|
654 |
rows= (ulong) strtoull(row[0], (char**) 0, 10); |
|
655 |
mysql_free_result(result); |
|
656 |
}
|
|
657 |
||
658 |
end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`"); |
|
659 |
if (wild && wild[0]) |
|
660 |
strxmov(end," like '",wild,"'",NullS); |
|
661 |
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) |
|
662 |
{
|
|
663 |
fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n", |
|
664 |
my_progname,db,table,mysql_error(mysql)); |
|
665 |
return 1; |
|
666 |
}
|
|
667 |
||
668 |
printf("Database: %s Table: %s", db, table); |
|
669 |
if (opt_count) |
|
670 |
printf(" Rows: %lu", rows); |
|
671 |
if (wild && wild[0]) |
|
672 |
printf(" Wildcard: %s",wild); |
|
673 |
putchar('\n'); |
|
674 |
||
675 |
print_res_header(result); |
|
676 |
while ((row=mysql_fetch_row(result))) |
|
677 |
print_res_row(result,row); |
|
678 |
print_res_top(result); |
|
679 |
if (opt_show_keys) |
|
680 |
{
|
|
681 |
end=strmov(strmov(strmov(query,"show keys from `"),table),"`"); |
|
682 |
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) |
|
683 |
{
|
|
684 |
fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n", |
|
685 |
my_progname,db,table,mysql_error(mysql)); |
|
686 |
return 1; |
|
687 |
}
|
|
688 |
if (mysql_num_rows(result)) |
|
689 |
{
|
|
690 |
print_res_header(result); |
|
691 |
while ((row=mysql_fetch_row(result))) |
|
692 |
print_res_row(result,row); |
|
693 |
print_res_top(result); |
|
694 |
}
|
|
695 |
else
|
|
696 |
puts("Table has no keys"); |
|
697 |
}
|
|
698 |
mysql_free_result(result); |
|
699 |
return 0; |
|
700 |
}
|
|
701 |
||
702 |
||
703 |
/*****************************************************************************
|
|
704 |
General functions to print a nice ascii-table from data
|
|
705 |
*****************************************************************************/
|
|
706 |
||
707 |
static void |
|
708 |
print_header(const char *header,uint head_length,...) |
|
709 |
{
|
|
710 |
va_list args; |
|
711 |
uint length,i,str_length,pre_space; |
|
712 |
const char *field; |
|
713 |
||
714 |
va_start(args,head_length); |
|
715 |
putchar('+'); |
|
716 |
field=header; length=head_length; |
|
717 |
for (;;) |
|
718 |
{
|
|
719 |
for (i=0 ; i < length+2 ; i++) |
|
720 |
putchar('-'); |
|
721 |
putchar('+'); |
|
722 |
if (!(field=va_arg(args,char *))) |
|
723 |
break; |
|
724 |
length=va_arg(args,uint); |
|
725 |
}
|
|
726 |
va_end(args); |
|
727 |
putchar('\n'); |
|
728 |
||
729 |
va_start(args,head_length); |
|
730 |
field=header; length=head_length; |
|
731 |
putchar('|'); |
|
732 |
for (;;) |
|
733 |
{
|
|
734 |
str_length=(uint) strlen(field); |
|
735 |
if (str_length > length) |
|
736 |
str_length=length+1; |
|
737 |
pre_space=(uint) (((int) length-(int) str_length)/2)+1; |
|
738 |
for (i=0 ; i < pre_space ; i++) |
|
739 |
putchar(' '); |
|
740 |
for (i = 0 ; i < str_length ; i++) |
|
741 |
putchar(field[i]); |
|
742 |
length=length+2-str_length-pre_space; |
|
743 |
for (i=0 ; i < length ; i++) |
|
744 |
putchar(' '); |
|
745 |
putchar('|'); |
|
746 |
if (!(field=va_arg(args,char *))) |
|
747 |
break; |
|
748 |
length=va_arg(args,uint); |
|
749 |
}
|
|
750 |
va_end(args); |
|
751 |
putchar('\n'); |
|
752 |
||
753 |
va_start(args,head_length); |
|
754 |
putchar('+'); |
|
755 |
field=header; length=head_length; |
|
756 |
for (;;) |
|
757 |
{
|
|
758 |
for (i=0 ; i < length+2 ; i++) |
|
759 |
putchar('-'); |
|
760 |
putchar('+'); |
|
761 |
if (!(field=va_arg(args,char *))) |
|
762 |
break; |
|
763 |
length=va_arg(args,uint); |
|
764 |
}
|
|
765 |
va_end(args); |
|
766 |
putchar('\n'); |
|
767 |
}
|
|
768 |
||
769 |
||
770 |
static void |
|
771 |
print_row(const char *header,uint head_length,...) |
|
772 |
{
|
|
773 |
va_list args; |
|
774 |
const char *field; |
|
775 |
uint i,length,field_length; |
|
776 |
||
777 |
va_start(args,head_length); |
|
778 |
field=header; length=head_length; |
|
779 |
for (;;) |
|
780 |
{
|
|
781 |
putchar('|'); |
|
782 |
putchar(' '); |
|
783 |
fputs(field,stdout); |
|
784 |
field_length=(uint) strlen(field); |
|
785 |
for (i=field_length ; i <= length ; i++) |
|
786 |
putchar(' '); |
|
787 |
if (!(field=va_arg(args,char *))) |
|
788 |
break; |
|
789 |
length=va_arg(args,uint); |
|
790 |
}
|
|
791 |
va_end(args); |
|
792 |
putchar('|'); |
|
793 |
putchar('\n'); |
|
794 |
}
|
|
795 |
||
796 |
||
797 |
static void |
|
798 |
print_trailer(uint head_length,...) |
|
799 |
{
|
|
800 |
va_list args; |
|
801 |
uint length,i; |
|
802 |
||
803 |
va_start(args,head_length); |
|
804 |
length=head_length; |
|
805 |
putchar('+'); |
|
806 |
for (;;) |
|
807 |
{
|
|
808 |
for (i=0 ; i < length+2 ; i++) |
|
809 |
putchar('-'); |
|
810 |
putchar('+'); |
|
811 |
if (!(length=va_arg(args,uint))) |
|
812 |
break; |
|
813 |
}
|
|
814 |
va_end(args); |
|
815 |
putchar('\n'); |
|
816 |
}
|
|
817 |
||
818 |
||
819 |
static void print_res_header(MYSQL_RES *result) |
|
820 |
{
|
|
821 |
MYSQL_FIELD *field; |
|
822 |
||
823 |
print_res_top(result); |
|
824 |
mysql_field_seek(result,0); |
|
825 |
putchar('|'); |
|
826 |
while ((field = mysql_fetch_field(result))) |
|
827 |
{
|
|
828 |
printf(" %-*s|",(int) field->max_length+1,field->name); |
|
829 |
}
|
|
830 |
putchar('\n'); |
|
831 |
print_res_top(result); |
|
832 |
}
|
|
833 |
||
834 |
||
835 |
static void print_res_top(MYSQL_RES *result) |
|
836 |
{
|
|
837 |
uint i,length; |
|
838 |
MYSQL_FIELD *field; |
|
839 |
||
840 |
putchar('+'); |
|
841 |
mysql_field_seek(result,0); |
|
842 |
while((field = mysql_fetch_field(result))) |
|
843 |
{
|
|
844 |
if ((length=(uint) strlen(field->name)) > field->max_length) |
|
845 |
field->max_length=length; |
|
846 |
else
|
|
847 |
length=field->max_length; |
|
848 |
for (i=length+2 ; i--> 0 ; ) |
|
849 |
putchar('-'); |
|
850 |
putchar('+'); |
|
851 |
}
|
|
852 |
putchar('\n'); |
|
853 |
}
|
|
854 |
||
855 |
||
856 |
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur) |
|
857 |
{
|
|
858 |
uint i,length; |
|
859 |
MYSQL_FIELD *field; |
|
860 |
putchar('|'); |
|
861 |
mysql_field_seek(result,0); |
|
862 |
for (i=0 ; i < mysql_num_fields(result); i++) |
|
863 |
{
|
|
864 |
field = mysql_fetch_field(result); |
|
865 |
length=field->max_length; |
|
866 |
printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : ""); |
|
867 |
}
|
|
868 |
putchar('\n'); |
|
869 |
}
|