~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqlshow.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

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