MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mysqlshow.c
1 /*
2  Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /* Show databases, tables or columns */
19 
20 #define SHOW_VERSION "9.10"
21 
22 #include "client_priv.h"
23 #include "my_default.h"
24 #include <my_sys.h>
25 #include <m_string.h>
26 #include <mysql.h>
27 #include <mysqld_error.h>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <sslopt-vars.h>
31 #include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
32 
33 static char * host=0, *opt_password=0, *user=0;
34 static my_bool opt_show_keys= 0, opt_compress= 0, opt_count=0, opt_status= 0;
35 static my_bool tty_password= 0, opt_table_type= 0;
36 static my_bool debug_info_flag= 0, debug_check_flag= 0;
37 static uint my_end_arg= 0;
38 static uint opt_verbose=0;
39 static char *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME;
40 static char *opt_plugin_dir= 0, *opt_default_auth= 0;
41 
42 #ifdef HAVE_SMEM
43 static char *shared_memory_base_name=0;
44 #endif
45 static uint opt_protocol=0;
46 static char *opt_bind_addr = NULL;
47 
48 static void get_options(int *argc,char ***argv);
49 static uint opt_mysql_port=0;
50 static int list_dbs(MYSQL *mysql,const char *wild);
51 static int list_tables(MYSQL *mysql,const char *db,const char *table);
52 static int list_table_status(MYSQL *mysql,const char *db,const char *table);
53 static int list_fields(MYSQL *mysql,const char *db,const char *table,
54  const char *field);
55 static void print_header(const char *header,uint head_length,...);
56 static void print_row(const char *header,uint head_length,...);
57 static void print_trailer(uint length,...);
58 static void print_res_header(MYSQL_RES *result);
59 static void print_res_top(MYSQL_RES *result);
60 static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur);
61 
62 static const char *load_default_groups[]= { "mysqlshow","client",0 };
63 static char * opt_mysql_unix_port=0;
64 
65 int main(int argc, char **argv)
66 {
67  int error;
68  my_bool first_argument_uses_wildcards=0;
69  char *wild;
70  MYSQL mysql;
71  MY_INIT(argv[0]);
72 
73  my_getopt_use_args_separator= TRUE;
74  if (load_defaults("my",load_default_groups,&argc,&argv))
75  exit(1);
76  my_getopt_use_args_separator= FALSE;
77 
78  get_options(&argc,&argv);
79 
80  wild=0;
81  if (argc)
82  {
83  char *pos= argv[argc-1], *to;
84  for (to= pos ; *pos ; pos++, to++)
85  {
86  switch (*pos) {
87  case '*':
88  *pos= '%';
89  first_argument_uses_wildcards= 1;
90  break;
91  case '?':
92  *pos= '_';
93  first_argument_uses_wildcards= 1;
94  break;
95  case '%':
96  case '_':
97  first_argument_uses_wildcards= 1;
98  break;
99  case '\\':
100  pos++;
101  default: break;
102  }
103  *to= *pos;
104  }
105  *to= *pos; /* just to copy a '\0' if '\\' was used */
106  }
107  if (first_argument_uses_wildcards)
108  wild= argv[--argc];
109  else if (argc == 3) /* We only want one field */
110  wild= argv[--argc];
111 
112  if (argc > 2)
113  {
114  fprintf(stderr,"%s: Too many arguments\n",my_progname);
115  exit(1);
116  }
117  mysql_init(&mysql);
118  if (opt_compress)
119  mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
120 #ifdef HAVE_OPENSSL
121  if (opt_use_ssl)
122  {
123  mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
124  opt_ssl_capath, opt_ssl_cipher);
125  mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
126  mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
127  }
128  mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
129  (char*)&opt_ssl_verify_server_cert);
130 #endif
131  if (opt_protocol)
132  mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
133  if (opt_bind_addr)
134  mysql_options(&mysql,MYSQL_OPT_BIND,opt_bind_addr);
135 #ifdef HAVE_SMEM
136  if (shared_memory_base_name)
137  mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
138 #endif
139  mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
140 
141  if (opt_plugin_dir && *opt_plugin_dir)
142  mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
143 
144  if (opt_default_auth && *opt_default_auth)
145  mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
146 
147  mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
148  mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
149  "program_name", "mysqlshow");
150  if (!(mysql_real_connect(&mysql,host,user,opt_password,
151  (first_argument_uses_wildcards) ? "" :
152  argv[0],opt_mysql_port,opt_mysql_unix_port,
153  0)))
154  {
155  fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
156  exit(1);
157  }
158  mysql.reconnect= 1;
159 
160  switch (argc) {
161  case 0: error=list_dbs(&mysql,wild); break;
162  case 1:
163  if (opt_status)
164  error=list_table_status(&mysql,argv[0],wild);
165  else
166  error=list_tables(&mysql,argv[0],wild);
167  break;
168  default:
169  if (opt_status && ! wild)
170  error=list_table_status(&mysql,argv[0],argv[1]);
171  else
172  error=list_fields(&mysql,argv[0],argv[1],wild);
173  break;
174  }
175  mysql_close(&mysql); /* Close & free connection */
176  my_free(opt_password);
177 #ifdef HAVE_SMEM
178  my_free(shared_memory_base_name);
179 #endif
180  my_end(my_end_arg);
181  exit(error ? 1 : 0);
182  return 0; /* No compiler warnings */
183 }
184 
185 static struct my_option my_long_options[] =
186 {
187  {"bind-address", 0, "IP address to bind to.",
188  (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
189  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
190  {"character-sets-dir", 'c', "Directory for character set files.",
191  &charsets_dir, &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
192  0, 0, 0, 0, 0},
193  {"default-character-set", OPT_DEFAULT_CHARSET,
194  "Set the default character set.", &default_charset,
195  &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
196  {"count", OPT_COUNT,
197  "Show number of rows per table (may be slow for non-MyISAM tables).",
198  &opt_count, &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
199  0, 0, 0},
200  {"compress", 'C', "Use compression in server/client protocol.",
201  &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
202  0, 0, 0},
203  {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
204  0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
205  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
206  &debug_check_flag, &debug_check_flag, 0,
207  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
208  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
209  &debug_info_flag, &debug_info_flag,
210  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
211  {"default_auth", OPT_DEFAULT_AUTH,
212  "Default authentication client-side plugin to use.",
213  &opt_default_auth, &opt_default_auth, 0,
214  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
215  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
216  0, 0, 0, 0, 0, 0},
217  {"host", 'h', "Connect to host.", &host, &host, 0, GET_STR,
218  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
219  {"status", 'i', "Shows a lot of extra information about each table.",
220  &opt_status, &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
221  0, 0},
222  {"keys", 'k', "Show keys for table.", &opt_show_keys,
223  &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
224  {"password", 'p',
225  "Password to use when connecting to server. If password is not given, it's "
226  "solicited on the tty.",
227  0, 0, 0, GET_PASSWORD, OPT_ARG, 0, 0, 0, 0, 0, 0},
228  {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
229  &opt_plugin_dir, &opt_plugin_dir, 0,
230  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
231  {"port", 'P', "Port number to use for connection or 0 for default to, in "
232  "order of preference, my.cnf, $MYSQL_TCP_PORT, "
233 #if MYSQL_PORT_DEFAULT == 0
234  "/etc/services, "
235 #endif
236  "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
237  &opt_mysql_port,
238  &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
239  0},
240 #ifdef __WIN__
241  {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
242  NO_ARG, 0, 0, 0, 0, 0, 0},
243 #endif
244  {"protocol", OPT_MYSQL_PROTOCOL,
245  "The protocol to use for connection (tcp, socket, pipe, memory).",
246  0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
247 #ifdef HAVE_SMEM
248  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
249  "Base name of shared memory.", &shared_memory_base_name,
250  &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG,
251  0, 0, 0, 0, 0, 0},
252 #endif
253  {"show-table-type", 't', "Show table type column.",
254  &opt_table_type, &opt_table_type, 0, GET_BOOL,
255  NO_ARG, 0, 0, 0, 0, 0, 0},
256  {"socket", 'S', "The socket file to use for connection.",
257  &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR,
258  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
259 #include <sslopt-longopts.h>
260 #ifndef DONT_ALLOW_USER_CHANGE
261  {"user", 'u', "User for login if not current user.", &user,
262  &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
263 #endif
264  {"verbose", 'v',
265  "More verbose output; you can use this multiple times to get even more "
266  "verbose output.",
267  0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
268  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
269  NO_ARG, 0, 0, 0, 0, 0, 0},
270  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
271 };
272 
273 
274 static void print_version(void)
275 {
276  printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
277  MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
278 }
279 
280 
281 static void usage(void)
282 {
283  print_version();
284  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
285  puts("Shows the structure of a MySQL database (databases, tables, and columns).\n");
286  printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
287  puts("\n\
288 If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\
289 what\'s matched by the wildcard is shown.\n\
290 If no database is given then all matching databases are shown.\n\
291 If no table is given, then all matching tables in database are shown.\n\
292 If no column is given, then all matching columns and column types in table\n\
293 are shown.");
294  print_defaults("my",load_default_groups);
295  my_print_help(my_long_options);
296  my_print_variables(my_long_options);
297 }
298 
299 
300 static my_bool
301 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
302  char *argument)
303 {
304  switch(optid) {
305  case 'v':
306  opt_verbose++;
307  break;
308  case 'p':
309  if (argument == disabled_my_option)
310  argument= (char*) ""; /* Don't require password */
311  if (argument)
312  {
313  char *start=argument;
314  my_free(opt_password);
315  opt_password=my_strdup(argument,MYF(MY_FAE));
316  while (*argument) *argument++= 'x'; /* Destroy argument */
317  if (*start)
318  start[1]=0; /* Cut length of argument */
319  tty_password= 0;
320  }
321  else
322  tty_password=1;
323  break;
324  case 'W':
325 #ifdef __WIN__
326  opt_protocol = MYSQL_PROTOCOL_PIPE;
327 #endif
328  break;
329  case OPT_MYSQL_PROTOCOL:
330  opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
331  opt->name);
332  break;
333  case '#':
334  DBUG_PUSH(argument ? argument : "d:t:o");
335  debug_check_flag= 1;
336  break;
337 #include <sslopt-case.h>
338  case 'V':
339  print_version();
340  exit(0);
341  break;
342  case '?':
343  case 'I': /* Info */
344  usage();
345  exit(0);
346  }
347  return 0;
348 }
349 
350 
351 static void
352 get_options(int *argc,char ***argv)
353 {
354  int ho_error;
355 
356  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
357  exit(ho_error);
358 
359  if (tty_password)
360  opt_password=get_tty_password(NullS);
361  if (opt_count)
362  {
363  /*
364  We need to set verbose to 2 as we need to change the output to include
365  the number-of-rows column
366  */
367  opt_verbose= 2;
368  }
369  if (debug_info_flag)
370  my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
371  if (debug_check_flag)
372  my_end_arg= MY_CHECK_ERROR;
373  return;
374 }
375 
376 
377 static int
378 list_dbs(MYSQL *mysql,const char *wild)
379 {
380  const char *header;
381  uint length, counter = 0;
382  ulong rowcount = 0L;
383  char tables[NAME_LEN+1], rows[NAME_LEN+1];
384  char query[255];
385  MYSQL_FIELD *field;
386  MYSQL_RES *result;
387  MYSQL_ROW row= NULL, rrow;
388 
389  if (!(result=mysql_list_dbs(mysql,wild)))
390  {
391  fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname,
392  mysql_error(mysql));
393  return 1;
394  }
395 
396  /*
397  If a wildcard was used, but there was only one row and it's name is an
398  exact match, we'll assume they really wanted to see the contents of that
399  database. This is because it is fairly common for database names to
400  contain the underscore (_), like INFORMATION_SCHEMA.
401  */
402  if (wild && mysql_num_rows(result) == 1)
403  {
404  row= mysql_fetch_row(result);
405  if (!my_strcasecmp(&my_charset_latin1, row[0], wild))
406  {
407  mysql_free_result(result);
408  if (opt_status)
409  return list_table_status(mysql, wild, NULL);
410  else
411  return list_tables(mysql, wild, NULL);
412  }
413  }
414 
415  if (wild)
416  printf("Wildcard: %s\n",wild);
417 
418  header="Databases";
419  length=(uint) strlen(header);
420  field=mysql_fetch_field(result);
421  if (length < field->max_length)
422  length=field->max_length;
423 
424  if (!opt_verbose)
425  print_header(header,length,NullS);
426  else if (opt_verbose == 1)
427  print_header(header,length,"Tables",6,NullS);
428  else
429  print_header(header,length,"Tables",6,"Total Rows",12,NullS);
430 
431  /* The first row may have already been read up above. */
432  while (row || (row= mysql_fetch_row(result)))
433  {
434  counter++;
435 
436  if (opt_verbose)
437  {
438  if (!(mysql_select_db(mysql,row[0])))
439  {
440  MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
441  if (mysql_affected_rows(mysql) > 0)
442  {
443  sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql));
444  rowcount = 0;
445  if (opt_verbose > 1)
446  {
447  /* Print the count of tables and rows for each database */
448  MYSQL_ROW trow;
449  while ((trow = mysql_fetch_row(tresult)))
450  {
451  sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
452  if (!(mysql_query(mysql,query)))
453  {
454  MYSQL_RES *rresult;
455  if ((rresult = mysql_store_result(mysql)))
456  {
457  rrow = mysql_fetch_row(rresult);
458  rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10);
459  mysql_free_result(rresult);
460  }
461  }
462  }
463  sprintf(rows,"%12lu",rowcount);
464  }
465  }
466  else
467  {
468  sprintf(tables,"%6d",0);
469  sprintf(rows,"%12d",0);
470  }
471  mysql_free_result(tresult);
472  }
473  else
474  {
475  strmov(tables,"N/A");
476  strmov(rows,"N/A");
477  }
478  }
479 
480  if (!opt_verbose)
481  print_row(row[0],length,0);
482  else if (opt_verbose == 1)
483  print_row(row[0],length,tables,6,NullS);
484  else
485  print_row(row[0],length,tables,6,rows,12,NullS);
486 
487  row= NULL;
488  }
489 
490  print_trailer(length,
491  (opt_verbose > 0 ? 6 : 0),
492  (opt_verbose > 1 ? 12 :0),
493  0);
494 
495  if (counter && opt_verbose)
496  printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : "");
497  mysql_free_result(result);
498  return 0;
499 }
500 
501 
502 static int
503 list_tables(MYSQL *mysql,const char *db,const char *table)
504 {
505  const char *header;
506  uint head_length, counter = 0;
507  char query[255], rows[NAME_LEN], fields[16];
508  MYSQL_FIELD *field;
509  MYSQL_RES *result;
510  MYSQL_ROW row, rrow;
511 
512  if (mysql_select_db(mysql,db))
513  {
514  fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db,
515  mysql_error(mysql));
516  return 1;
517  }
518  if (table)
519  {
520  /*
521  We just hijack the 'rows' variable for a bit to store the escaped
522  table name
523  */
524  mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table));
525  my_snprintf(query, sizeof(query), "show%s tables like '%s'",
526  opt_table_type ? " full" : "", rows);
527  }
528  else
529  my_snprintf(query, sizeof(query), "show%s tables",
530  opt_table_type ? " full" : "");
531  if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql)))
532  {
533  fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db,
534  mysql_error(mysql));
535  exit(1);
536  }
537  printf("Database: %s",db);
538  if (table)
539  printf(" Wildcard: %s",table);
540  putchar('\n');
541 
542  header="Tables";
543  head_length=(uint) strlen(header);
544  field=mysql_fetch_field(result);
545  if (head_length < field->max_length)
546  head_length=field->max_length;
547 
548  if (opt_table_type)
549  {
550  if (!opt_verbose)
551  print_header(header,head_length,"table_type",10,NullS);
552  else if (opt_verbose == 1)
553  print_header(header,head_length,"table_type",10,"Columns",8,NullS);
554  else
555  {
556  print_header(header,head_length,"table_type",10,"Columns",8,
557  "Total Rows",10,NullS);
558  }
559  }
560  else
561  {
562  if (!opt_verbose)
563  print_header(header,head_length,NullS);
564  else if (opt_verbose == 1)
565  print_header(header,head_length,"Columns",8,NullS);
566  else
567  print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
568  }
569 
570  while ((row = mysql_fetch_row(result)))
571  {
572  counter++;
573  if (opt_verbose > 0)
574  {
575  if (!(mysql_select_db(mysql,db)))
576  {
577  MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL);
578  ulong rowcount=0L;
579  if (!rresult)
580  {
581  strmov(fields,"N/A");
582  strmov(rows,"N/A");
583  }
584  else
585  {
586  sprintf(fields,"%8u",(uint) mysql_num_fields(rresult));
587  mysql_free_result(rresult);
588 
589  if (opt_verbose > 1)
590  {
591  /* Print the count of rows for each table */
592  sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
593  if (!(mysql_query(mysql,query)))
594  {
595  if ((rresult = mysql_store_result(mysql)))
596  {
597  rrow = mysql_fetch_row(rresult);
598  rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10);
599  mysql_free_result(rresult);
600  }
601  sprintf(rows,"%10lu",rowcount);
602  }
603  else
604  sprintf(rows,"%10d",0);
605  }
606  }
607  }
608  else
609  {
610  strmov(fields,"N/A");
611  strmov(rows,"N/A");
612  }
613  }
614  if (opt_table_type)
615  {
616  if (!opt_verbose)
617  print_row(row[0],head_length,row[1],10,NullS);
618  else if (opt_verbose == 1)
619  print_row(row[0],head_length,row[1],10,fields,8,NullS);
620  else
621  print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS);
622  }
623  else
624  {
625  if (!opt_verbose)
626  print_row(row[0],head_length,NullS);
627  else if (opt_verbose == 1)
628  print_row(row[0],head_length, fields,8, NullS);
629  else
630  print_row(row[0],head_length, fields,8, rows,10, NullS);
631  }
632  }
633 
634  print_trailer(head_length,
635  (opt_table_type ? 10 : opt_verbose > 0 ? 8 : 0),
636  (opt_table_type ? (opt_verbose > 0 ? 8 : 0)
637  : (opt_verbose > 1 ? 10 :0)),
638  !opt_table_type ? 0 : opt_verbose > 1 ? 10 :0,
639  0);
640 
641  if (counter && opt_verbose)
642  printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : "");
643 
644  mysql_free_result(result);
645  return 0;
646 }
647 
648 
649 static int
650 list_table_status(MYSQL *mysql,const char *db,const char *wild)
651 {
652  char query[1024],*end;
653  MYSQL_RES *result;
654  MYSQL_ROW row;
655 
656  end=strxmov(query,"show table status from `",db,"`",NullS);
657  if (wild && wild[0])
658  strxmov(end," like '",wild,"'",NullS);
659  if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
660  {
661  fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n",
662  my_progname,db,wild ? wild : "",mysql_error(mysql));
663  if (mysql_errno(mysql) == ER_PARSE_ERROR)
664  fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n");
665  return 1;
666  }
667 
668  printf("Database: %s",db);
669  if (wild)
670  printf(" Wildcard: %s",wild);
671  putchar('\n');
672 
673  print_res_header(result);
674  while ((row=mysql_fetch_row(result)))
675  print_res_row(result,row);
676  print_res_top(result);
677  mysql_free_result(result);
678  return 0;
679 }
680 
681 /*
682  list fields uses field interface as an example of how to parse
683  a MYSQL FIELD
684 */
685 
686 static int
687 list_fields(MYSQL *mysql,const char *db,const char *table,
688  const char *wild)
689 {
690  char query[1024],*end;
691  MYSQL_RES *result;
692  MYSQL_ROW row;
693  ulong UNINIT_VAR(rows);
694 
695  if (mysql_select_db(mysql,db))
696  {
697  fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db,
698  mysql_error(mysql));
699  return 1;
700  }
701 
702  if (opt_count)
703  {
704  sprintf(query,"select count(*) from `%s`", table);
705  if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
706  {
707  fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
708  my_progname,db,table,mysql_error(mysql));
709  return 1;
710  }
711  row= mysql_fetch_row(result);
712  rows= (ulong) strtoull(row[0], (char**) 0, 10);
713  mysql_free_result(result);
714  }
715 
716  end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
717  if (wild && wild[0])
718  strxmov(end," like '",wild,"'",NullS);
719  if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
720  {
721  fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n",
722  my_progname,db,table,mysql_error(mysql));
723  return 1;
724  }
725 
726  printf("Database: %s Table: %s", db, table);
727  if (opt_count)
728  printf(" Rows: %lu", rows);
729  if (wild && wild[0])
730  printf(" Wildcard: %s",wild);
731  putchar('\n');
732 
733  print_res_header(result);
734  while ((row=mysql_fetch_row(result)))
735  print_res_row(result,row);
736  print_res_top(result);
737  if (opt_show_keys)
738  {
739  end=strmov(strmov(strmov(query,"show keys from `"),table),"`");
740  if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
741  {
742  fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n",
743  my_progname,db,table,mysql_error(mysql));
744  return 1;
745  }
746  if (mysql_num_rows(result))
747  {
748  print_res_header(result);
749  while ((row=mysql_fetch_row(result)))
750  print_res_row(result,row);
751  print_res_top(result);
752  }
753  else
754  puts("Table has no keys");
755  }
756  mysql_free_result(result);
757  return 0;
758 }
759 
760 
761 /*****************************************************************************
762  General functions to print a nice ascii-table from data
763 *****************************************************************************/
764 
765 static void
766 print_header(const char *header,uint head_length,...)
767 {
768  va_list args;
769  uint length,i,str_length,pre_space;
770  const char *field;
771 
772  va_start(args,head_length);
773  putchar('+');
774  field=header; length=head_length;
775  for (;;)
776  {
777  for (i=0 ; i < length+2 ; i++)
778  putchar('-');
779  putchar('+');
780  if (!(field=va_arg(args,char *)))
781  break;
782  length=va_arg(args,uint);
783  }
784  va_end(args);
785  putchar('\n');
786 
787  va_start(args,head_length);
788  field=header; length=head_length;
789  putchar('|');
790  for (;;)
791  {
792  str_length=(uint) strlen(field);
793  if (str_length > length)
794  str_length=length+1;
795  pre_space=(uint) (((int) length-(int) str_length)/2)+1;
796  for (i=0 ; i < pre_space ; i++)
797  putchar(' ');
798  for (i = 0 ; i < str_length ; i++)
799  putchar(field[i]);
800  length=length+2-str_length-pre_space;
801  for (i=0 ; i < length ; i++)
802  putchar(' ');
803  putchar('|');
804  if (!(field=va_arg(args,char *)))
805  break;
806  length=va_arg(args,uint);
807  }
808  va_end(args);
809  putchar('\n');
810 
811  va_start(args,head_length);
812  putchar('+');
813  field=header; length=head_length;
814  for (;;)
815  {
816  for (i=0 ; i < length+2 ; i++)
817  putchar('-');
818  putchar('+');
819  if (!(field=va_arg(args,char *)))
820  break;
821  length=va_arg(args,uint);
822  }
823  va_end(args);
824  putchar('\n');
825 }
826 
827 
828 static void
829 print_row(const char *header,uint head_length,...)
830 {
831  va_list args;
832  const char *field;
833  uint i,length,field_length;
834 
835  va_start(args,head_length);
836  field=header; length=head_length;
837  for (;;)
838  {
839  putchar('|');
840  putchar(' ');
841  fputs(field,stdout);
842  field_length=(uint) strlen(field);
843  for (i=field_length ; i <= length ; i++)
844  putchar(' ');
845  if (!(field=va_arg(args,char *)))
846  break;
847  length=va_arg(args,uint);
848  }
849  va_end(args);
850  putchar('|');
851  putchar('\n');
852 }
853 
854 
855 static void
856 print_trailer(uint head_length,...)
857 {
858  va_list args;
859  uint length,i;
860 
861  va_start(args,head_length);
862  length=head_length;
863  putchar('+');
864  for (;;)
865  {
866  for (i=0 ; i < length+2 ; i++)
867  putchar('-');
868  putchar('+');
869  if (!(length=va_arg(args,uint)))
870  break;
871  }
872  va_end(args);
873  putchar('\n');
874 }
875 
876 
877 static void print_res_header(MYSQL_RES *result)
878 {
879  MYSQL_FIELD *field;
880 
881  print_res_top(result);
882  mysql_field_seek(result,0);
883  putchar('|');
884  while ((field = mysql_fetch_field(result)))
885  {
886  printf(" %-*s|",(int) field->max_length+1,field->name);
887  }
888  putchar('\n');
889  print_res_top(result);
890 }
891 
892 
893 static void print_res_top(MYSQL_RES *result)
894 {
895  uint i,length;
896  MYSQL_FIELD *field;
897 
898  putchar('+');
899  mysql_field_seek(result,0);
900  while((field = mysql_fetch_field(result)))
901  {
902  if ((length=(uint) strlen(field->name)) > field->max_length)
903  field->max_length=length;
904  else
905  length=field->max_length;
906  for (i=length+2 ; i--> 0 ; )
907  putchar('-');
908  putchar('+');
909  }
910  putchar('\n');
911 }
912 
913 
914 static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur)
915 {
916  uint i,length;
917  MYSQL_FIELD *field;
918  putchar('|');
919  mysql_field_seek(result,0);
920  for (i=0 ; i < mysql_num_fields(result); i++)
921  {
922  field = mysql_fetch_field(result);
923  length=field->max_length;
924  printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");
925  }
926  putchar('\n');
927 }