~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqlshow.c

Removed SCCS references.

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
  {"character-sets-dir", 'c', "Directory where character sets are.",
 
162
   (uchar**) &charsets_dir, (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
 
163
   0, 0, 0, 0, 0},
 
164
  {"default-character-set", OPT_DEFAULT_CHARSET,
 
165
   "Set the default character set.", (uchar**) &default_charset,
 
166
   (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
167
  {"count", OPT_COUNT,
 
168
   "Show number of rows per table (may be slow for not MyISAM tables)",
 
169
   (uchar**) &opt_count, (uchar**) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
170
   0, 0, 0},
 
171
  {"compress", 'C', "Use compression in server/client protocol.",
 
172
   (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
 
173
   0, 0, 0},
 
174
  {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
 
175
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
176
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
 
177
   (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
 
178
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
179
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
 
180
   (uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
 
181
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
182
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
 
183
   0, 0, 0, 0, 0, 0},
 
184
  {"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR,
 
185
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
186
  {"status", 'i', "Shows a lot of extra information about each table.",
 
187
   (uchar**) &opt_status, (uchar**) &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
188
   0, 0},
 
189
  {"keys", 'k', "Show keys for table.", (uchar**) &opt_show_keys,
 
190
   (uchar**) &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
191
  {"password", 'p',
 
192
   "Password to use when connecting to server. If password is not given it's asked from the tty.",
 
193
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
194
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
 
195
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
 
196
#if MYSQL_PORT_DEFAULT == 0
 
197
   "/etc/services, "
 
198
#endif
 
199
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
 
200
   (uchar**) &opt_mysql_port,
 
201
   (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
 
202
   0},
 
203
  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
 
204
   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
205
#ifdef HAVE_SMEM
 
206
  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
 
207
   "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
 
208
   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
209
#endif
 
210
  {"show-table-type", 't', "Show table type column.",
 
211
   (uchar**) &opt_table_type, (uchar**) &opt_table_type, 0, GET_BOOL,
 
212
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
213
  {"socket", 'S', "Socket file to use for connection.",
 
214
   (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
 
215
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
216
#ifndef DONT_ALLOW_USER_CHANGE
 
217
  {"user", 'u', "User for login if not current user.", (uchar**) &user,
 
218
   (uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
219
#endif
 
220
  {"verbose", 'v',
 
221
   "More verbose output; You can use this multiple times to get even more verbose output.",
 
222
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
223
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
 
224
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
225
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
226
};
 
227
 
 
228
  
 
229
#include <help_start.h>
 
230
 
 
231
static void print_version(void)
 
232
{
 
233
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
 
234
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
 
235
}
 
236
 
 
237
 
 
238
static void usage(void)
 
239
{
 
240
  print_version();
 
241
  puts("Copyright (C) 2000-2006 MySQL AB");
 
242
  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");
 
243
  puts("Shows the structure of a mysql database (databases,tables and columns)\n");
 
244
  printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
 
245
  puts("\n\
 
246
If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\
 
247
what\'s matched by the wildcard is shown.\n\
 
248
If no database is given then all matching databases are shown.\n\
 
249
If no table is given then all matching tables in database are shown\n\
 
250
If no column is given then all matching columns and columntypes in table\n\
 
251
are shown");
 
252
  print_defaults("my",load_default_groups);
 
253
  my_print_help(my_long_options);
 
254
  my_print_variables(my_long_options);
 
255
}
 
256
 
 
257
#include <help_end.h>
 
258
 
 
259
static my_bool
 
260
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
 
261
               char *argument)
 
262
{
 
263
  switch(optid) {
 
264
  case 'v':
 
265
    opt_verbose++;
 
266
    break;
 
267
  case 'p':
 
268
    if (argument)
 
269
    {
 
270
      char *start=argument;
 
271
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
 
272
      opt_password=my_strdup(argument,MYF(MY_FAE));
 
273
      while (*argument) *argument++= 'x';               /* Destroy argument */
 
274
      if (*start)
 
275
        start[1]=0;                             /* Cut length of argument */
 
276
      tty_password= 0;
 
277
    }
 
278
    else
 
279
      tty_password=1;
 
280
    break;
 
281
  case OPT_MYSQL_PROTOCOL:
 
282
    opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
 
283
                                    opt->name);
 
284
    break;
 
285
  case '#':
 
286
    DBUG_PUSH(argument ? argument : "d:t:o");
 
287
    debug_check_flag= 1;
 
288
    break;
 
289
  case 'V':
 
290
    print_version();
 
291
    exit(0);
 
292
    break;
 
293
  case '?':
 
294
  case 'I':                                     /* Info */
 
295
    usage();
 
296
    exit(0);
 
297
  }
 
298
  return 0;
 
299
}
 
300
 
 
301
 
 
302
static void
 
303
get_options(int *argc,char ***argv)
 
304
{
 
305
  int ho_error;
 
306
 
 
307
  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
 
308
    exit(ho_error);
 
309
  
 
310
  if (tty_password)
 
311
    opt_password=get_tty_password(NullS);
 
312
  if (opt_count)
 
313
  {
 
314
    /*
 
315
      We need to set verbose to 2 as we need to change the output to include
 
316
      the number-of-rows column
 
317
    */
 
318
    opt_verbose= 2;
 
319
  }
 
320
  if (debug_info_flag)
 
321
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
 
322
  if (debug_check_flag)
 
323
    my_end_arg= MY_CHECK_ERROR;
 
324
  return;
 
325
}
 
326
 
 
327
 
 
328
static int
 
329
list_dbs(MYSQL *mysql,const char *wild)
 
330
{
 
331
  const char *header;
 
332
  uint length, counter = 0;
 
333
  ulong rowcount = 0L;
 
334
  char tables[NAME_LEN+1], rows[NAME_LEN+1];
 
335
  char query[255];
 
336
  MYSQL_FIELD *field;
 
337
  MYSQL_RES *result;
 
338
  MYSQL_ROW row= NULL, rrow;
 
339
 
 
340
  if (!(result=mysql_list_dbs(mysql,wild)))
 
341
  {
 
342
    fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname,
 
343
            mysql_error(mysql));
 
344
    return 1;
 
345
  }
 
346
 
 
347
  /*
 
348
    If a wildcard was used, but there was only one row and it's name is an
 
349
    exact match, we'll assume they really wanted to see the contents of that
 
350
    database. This is because it is fairly common for database names to
 
351
    contain the underscore (_), like INFORMATION_SCHEMA.
 
352
   */
 
353
  if (wild && mysql_num_rows(result) == 1)
 
354
  {
 
355
    row= mysql_fetch_row(result);
 
356
    if (!my_strcasecmp(&my_charset_latin1, row[0], wild))
 
357
    {
 
358
      mysql_free_result(result);
 
359
      if (opt_status)
 
360
        return list_table_status(mysql, wild, NULL);
 
361
      else
 
362
        return list_tables(mysql, wild, NULL);
 
363
    }
 
364
  }
 
365
 
 
366
  if (wild)
 
367
    printf("Wildcard: %s\n",wild);
 
368
 
 
369
  header="Databases";
 
370
  length=(uint) strlen(header);
 
371
  field=mysql_fetch_field(result);
 
372
  if (length < field->max_length)
 
373
    length=field->max_length;
 
374
 
 
375
  if (!opt_verbose)
 
376
    print_header(header,length,NullS);
 
377
  else if (opt_verbose == 1)
 
378
    print_header(header,length,"Tables",6,NullS);
 
379
  else
 
380
    print_header(header,length,"Tables",6,"Total Rows",12,NullS);
 
381
 
 
382
  /* The first row may have already been read up above. */
 
383
  while (row || (row= mysql_fetch_row(result)))
 
384
  {
 
385
    counter++;
 
386
 
 
387
    if (opt_verbose)
 
388
    {
 
389
      if (!(mysql_select_db(mysql,row[0])))
 
390
      {
 
391
        MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
 
392
        if (mysql_affected_rows(mysql) > 0)
 
393
        {
 
394
          sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql));
 
395
          rowcount = 0;
 
396
          if (opt_verbose > 1)
 
397
          {
 
398
            /* Print the count of tables and rows for each database */
 
399
            MYSQL_ROW trow;
 
400
            while ((trow = mysql_fetch_row(tresult)))
 
401
            {
 
402
              sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
 
403
              if (!(mysql_query(mysql,query)))
 
404
              {
 
405
                MYSQL_RES *rresult;
 
406
                if ((rresult = mysql_store_result(mysql)))
 
407
                {
 
408
                  rrow = mysql_fetch_row(rresult);
 
409
                  rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10);
 
410
                  mysql_free_result(rresult);
 
411
                }
 
412
              }
 
413
            }
 
414
            sprintf(rows,"%12lu",rowcount);
 
415
          }
 
416
        }
 
417
        else
 
418
        {
 
419
          sprintf(tables,"%6d",0);
 
420
          sprintf(rows,"%12d",0);
 
421
        }
 
422
        mysql_free_result(tresult);
 
423
      }
 
424
      else
 
425
      {
 
426
        strmov(tables,"N/A");
 
427
        strmov(rows,"N/A");
 
428
      }
 
429
    }
 
430
 
 
431
    if (!opt_verbose)
 
432
      print_row(row[0],length,0);
 
433
    else if (opt_verbose == 1)
 
434
      print_row(row[0],length,tables,6,NullS);
 
435
    else
 
436
      print_row(row[0],length,tables,6,rows,12,NullS);
 
437
 
 
438
    row= NULL;
 
439
  }
 
440
 
 
441
  print_trailer(length,
 
442
                (opt_verbose > 0 ? 6 : 0),
 
443
                (opt_verbose > 1 ? 12 :0),
 
444
                0);
 
445
 
 
446
  if (counter && opt_verbose)
 
447
    printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : "");
 
448
  mysql_free_result(result);
 
449
  return 0;
 
450
}
 
451
 
 
452
 
 
453
static int
 
454
list_tables(MYSQL *mysql,const char *db,const char *table)
 
455
{
 
456
  const char *header;
 
457
  uint head_length, counter = 0;
 
458
  char query[255], rows[NAME_LEN], fields[16];
 
459
  MYSQL_FIELD *field;
 
460
  MYSQL_RES *result;
 
461
  MYSQL_ROW row, rrow;
 
462
 
 
463
  if (mysql_select_db(mysql,db))
 
464
  {
 
465
    fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db,
 
466
            mysql_error(mysql));
 
467
    return 1;
 
468
  }
 
469
  if (table)
 
470
  {
 
471
    /*
 
472
      We just hijack the 'rows' variable for a bit to store the escaped
 
473
      table name
 
474
    */
 
475
    mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table));
 
476
    my_snprintf(query, sizeof(query), "show%s tables like '%s'",
 
477
                opt_table_type ? " full" : "", rows);
 
478
  }
 
479
  else
 
480
    my_snprintf(query, sizeof(query), "show%s tables",
 
481
                opt_table_type ? " full" : "");
 
482
  if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql)))
 
483
  {
 
484
    fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db,
 
485
            mysql_error(mysql));
 
486
    exit(1);
 
487
  }
 
488
  printf("Database: %s",db);
 
489
  if (table)
 
490
    printf("  Wildcard: %s",table);
 
491
  putchar('\n');
 
492
 
 
493
  header="Tables";
 
494
  head_length=(uint) strlen(header);
 
495
  field=mysql_fetch_field(result);
 
496
  if (head_length < field->max_length)
 
497
    head_length=field->max_length;
 
498
 
 
499
  if (opt_table_type)
 
500
  {
 
501
    if (!opt_verbose)
 
502
      print_header(header,head_length,"table_type",10,NullS);
 
503
    else if (opt_verbose == 1)
 
504
      print_header(header,head_length,"table_type",10,"Columns",8,NullS);
 
505
    else
 
506
    {
 
507
      print_header(header,head_length,"table_type",10,"Columns",8,
 
508
                   "Total Rows",10,NullS);
 
509
    }
 
510
  }
 
511
  else
 
512
  {
 
513
    if (!opt_verbose)
 
514
      print_header(header,head_length,NullS);
 
515
    else if (opt_verbose == 1)
 
516
      print_header(header,head_length,"Columns",8,NullS);
 
517
    else
 
518
      print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
 
519
  }
 
520
 
 
521
  while ((row = mysql_fetch_row(result)))
 
522
  {
 
523
    counter++;
 
524
    if (opt_verbose > 0)
 
525
    {
 
526
      if (!(mysql_select_db(mysql,db)))
 
527
      {
 
528
        MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL);
 
529
        ulong rowcount=0L;
 
530
        if (!rresult)
 
531
        {
 
532
          strmov(fields,"N/A");
 
533
          strmov(rows,"N/A");
 
534
        }
 
535
        else
 
536
        {
 
537
          sprintf(fields,"%8u",(uint) mysql_num_fields(rresult));
 
538
          mysql_free_result(rresult);
 
539
 
 
540
          if (opt_verbose > 1)
 
541
          {
 
542
            /* Print the count of rows for each table */
 
543
            sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
 
544
            if (!(mysql_query(mysql,query)))
 
545
            {
 
546
              if ((rresult = mysql_store_result(mysql)))
 
547
              {
 
548
                rrow = mysql_fetch_row(rresult);
 
549
                rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10);
 
550
                mysql_free_result(rresult);
 
551
              }
 
552
              sprintf(rows,"%10lu",rowcount);
 
553
            }
 
554
            else
 
555
              sprintf(rows,"%10d",0);
 
556
          }
 
557
        }
 
558
      }
 
559
      else
 
560
      {
 
561
        strmov(fields,"N/A");
 
562
        strmov(rows,"N/A");
 
563
      }
 
564
    }
 
565
    if (opt_table_type)
 
566
    {
 
567
      if (!opt_verbose)
 
568
        print_row(row[0],head_length,row[1],10,NullS);
 
569
      else if (opt_verbose == 1)
 
570
        print_row(row[0],head_length,row[1],10,fields,8,NullS);
 
571
      else
 
572
        print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS);
 
573
    }
 
574
    else
 
575
    {
 
576
      if (!opt_verbose)
 
577
        print_row(row[0],head_length,NullS);
 
578
      else if (opt_verbose == 1)
 
579
        print_row(row[0],head_length, fields,8, NullS);
 
580
      else
 
581
        print_row(row[0],head_length, fields,8, rows,10, NullS);
 
582
    }
 
583
  }
 
584
 
 
585
  print_trailer(head_length,
 
586
                (opt_table_type ? 10 : opt_verbose > 0 ? 8 : 0),
 
587
                (opt_table_type ? (opt_verbose > 0 ? 8 : 0) 
 
588
                 : (opt_verbose > 1 ? 10 :0)),
 
589
                !opt_table_type ? 0 : opt_verbose > 1 ? 10 :0,
 
590
                0);
 
591
 
 
592
  if (counter && opt_verbose)
 
593
    printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : "");
 
594
 
 
595
  mysql_free_result(result);
 
596
  return 0;
 
597
}
 
598
 
 
599
 
 
600
static int
 
601
list_table_status(MYSQL *mysql,const char *db,const char *wild)
 
602
{
 
603
  char query[1024],*end;
 
604
  MYSQL_RES *result;
 
605
  MYSQL_ROW row;
 
606
 
 
607
  end=strxmov(query,"show table status from `",db,"`",NullS);
 
608
  if (wild && wild[0])
 
609
    strxmov(end," like '",wild,"'",NullS);
 
610
  if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
 
611
  {
 
612
    fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n",
 
613
            my_progname,db,wild ? wild : "",mysql_error(mysql));
 
614
    if (mysql_errno(mysql) == ER_PARSE_ERROR)
 
615
      fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n");
 
616
    return 1;
 
617
  }
 
618
 
 
619
  printf("Database: %s",db);
 
620
  if (wild)
 
621
    printf("  Wildcard: %s",wild);
 
622
  putchar('\n');
 
623
 
 
624
  print_res_header(result);
 
625
  while ((row=mysql_fetch_row(result)))
 
626
    print_res_row(result,row);
 
627
  print_res_top(result);
 
628
  mysql_free_result(result);
 
629
  return 0;
 
630
}
 
631
 
 
632
/*
 
633
  list fields uses field interface as an example of how to parse
 
634
  a MYSQL FIELD
 
635
*/
 
636
 
 
637
static int
 
638
list_fields(MYSQL *mysql,const char *db,const char *table,
 
639
            const char *wild)
 
640
{
 
641
  char query[1024],*end;
 
642
  MYSQL_RES *result;
 
643
  MYSQL_ROW row;
 
644
  ulong rows= 0;
 
645
 
 
646
  if (mysql_select_db(mysql,db))
 
647
  {
 
648
    fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db,
 
649
            mysql_error(mysql));
 
650
    return 1;
 
651
  }
 
652
 
 
653
  if (opt_count)
 
654
  {
 
655
    sprintf(query,"select count(*) from `%s`", table);
 
656
    if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
 
657
    {
 
658
      fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
 
659
              my_progname,db,table,mysql_error(mysql));
 
660
      return 1;
 
661
    }
 
662
    row= mysql_fetch_row(result);
 
663
    rows= (ulong) strtoull(row[0], (char**) 0, 10);
 
664
    mysql_free_result(result);
 
665
  }
 
666
 
 
667
  end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
 
668
  if (wild && wild[0])
 
669
    strxmov(end," like '",wild,"'",NullS);
 
670
  if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
 
671
  {
 
672
    fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n",
 
673
            my_progname,db,table,mysql_error(mysql));
 
674
    return 1;
 
675
  }
 
676
 
 
677
  printf("Database: %s  Table: %s", db, table);
 
678
  if (opt_count)
 
679
    printf("  Rows: %lu", rows);
 
680
  if (wild && wild[0])
 
681
    printf("  Wildcard: %s",wild);
 
682
  putchar('\n');
 
683
 
 
684
  print_res_header(result);
 
685
  while ((row=mysql_fetch_row(result)))
 
686
    print_res_row(result,row);
 
687
  print_res_top(result);
 
688
  if (opt_show_keys)
 
689
  {
 
690
    end=strmov(strmov(strmov(query,"show keys from `"),table),"`");
 
691
    if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
 
692
    {
 
693
      fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n",
 
694
              my_progname,db,table,mysql_error(mysql));
 
695
      return 1;
 
696
    }
 
697
    if (mysql_num_rows(result))
 
698
    {
 
699
      print_res_header(result);
 
700
      while ((row=mysql_fetch_row(result)))
 
701
        print_res_row(result,row);
 
702
      print_res_top(result);
 
703
    }
 
704
    else
 
705
      puts("Table has no keys");
 
706
  }
 
707
  mysql_free_result(result);
 
708
  return 0;
 
709
}
 
710
 
 
711
 
 
712
/*****************************************************************************
 
713
 General functions to print a nice ascii-table from data
 
714
*****************************************************************************/
 
715
 
 
716
static void
 
717
print_header(const char *header,uint head_length,...)
 
718
{
 
719
  va_list args;
 
720
  uint length,i,str_length,pre_space;
 
721
  const char *field;
 
722
 
 
723
  va_start(args,head_length);
 
724
  putchar('+');
 
725
  field=header; length=head_length;
 
726
  for (;;)
 
727
  {
 
728
    for (i=0 ; i < length+2 ; i++)
 
729
      putchar('-');
 
730
    putchar('+');
 
731
    if (!(field=va_arg(args,char *)))
 
732
      break;
 
733
    length=va_arg(args,uint);
 
734
  }
 
735
  va_end(args);
 
736
  putchar('\n');
 
737
 
 
738
  va_start(args,head_length);
 
739
  field=header; length=head_length;
 
740
  putchar('|');
 
741
  for (;;)
 
742
  {
 
743
    str_length=(uint) strlen(field);
 
744
    if (str_length > length)
 
745
      str_length=length+1;
 
746
    pre_space=(uint) (((int) length-(int) str_length)/2)+1;
 
747
    for (i=0 ; i < pre_space ; i++)
 
748
      putchar(' ');
 
749
    for (i = 0 ; i < str_length ; i++)
 
750
      putchar(field[i]);
 
751
    length=length+2-str_length-pre_space;
 
752
    for (i=0 ; i < length ; i++)
 
753
      putchar(' ');
 
754
    putchar('|');
 
755
    if (!(field=va_arg(args,char *)))
 
756
      break;
 
757
    length=va_arg(args,uint);
 
758
  }
 
759
  va_end(args);
 
760
  putchar('\n');
 
761
 
 
762
  va_start(args,head_length);
 
763
  putchar('+');
 
764
  field=header; length=head_length;
 
765
  for (;;)
 
766
  {
 
767
    for (i=0 ; i < length+2 ; i++)
 
768
      putchar('-');
 
769
    putchar('+');
 
770
    if (!(field=va_arg(args,char *)))
 
771
      break;
 
772
    length=va_arg(args,uint);
 
773
  }
 
774
  va_end(args);
 
775
  putchar('\n');
 
776
}
 
777
 
 
778
 
 
779
static void
 
780
print_row(const char *header,uint head_length,...)
 
781
{
 
782
  va_list args;
 
783
  const char *field;
 
784
  uint i,length,field_length;
 
785
 
 
786
  va_start(args,head_length);
 
787
  field=header; length=head_length;
 
788
  for (;;)
 
789
  {
 
790
    putchar('|');
 
791
    putchar(' ');
 
792
    fputs(field,stdout);
 
793
    field_length=(uint) strlen(field);
 
794
    for (i=field_length ; i <= length ; i++)
 
795
      putchar(' ');
 
796
    if (!(field=va_arg(args,char *)))
 
797
      break;
 
798
    length=va_arg(args,uint);
 
799
  }
 
800
  va_end(args);
 
801
  putchar('|');
 
802
  putchar('\n');
 
803
}
 
804
 
 
805
 
 
806
static void
 
807
print_trailer(uint head_length,...)
 
808
{
 
809
  va_list args;
 
810
  uint length,i;
 
811
 
 
812
  va_start(args,head_length);
 
813
  length=head_length;
 
814
  putchar('+');
 
815
  for (;;)
 
816
  {
 
817
    for (i=0 ; i < length+2 ; i++)
 
818
      putchar('-');
 
819
    putchar('+');
 
820
    if (!(length=va_arg(args,uint)))
 
821
      break;
 
822
  }
 
823
  va_end(args);
 
824
  putchar('\n');
 
825
}
 
826
 
 
827
 
 
828
static void print_res_header(MYSQL_RES *result)
 
829
{
 
830
  MYSQL_FIELD *field;
 
831
 
 
832
  print_res_top(result);
 
833
  mysql_field_seek(result,0);
 
834
  putchar('|');
 
835
  while ((field = mysql_fetch_field(result)))
 
836
  {
 
837
    printf(" %-*s|",(int) field->max_length+1,field->name);
 
838
  }
 
839
  putchar('\n');
 
840
  print_res_top(result);
 
841
}
 
842
 
 
843
 
 
844
static void print_res_top(MYSQL_RES *result)
 
845
{
 
846
  uint i,length;
 
847
  MYSQL_FIELD *field;
 
848
 
 
849
  putchar('+');
 
850
  mysql_field_seek(result,0);
 
851
  while((field = mysql_fetch_field(result)))
 
852
  {
 
853
    if ((length=(uint) strlen(field->name)) > field->max_length)
 
854
      field->max_length=length;
 
855
    else
 
856
      length=field->max_length;
 
857
    for (i=length+2 ; i--> 0 ; )
 
858
      putchar('-');
 
859
    putchar('+');
 
860
  }
 
861
  putchar('\n');
 
862
}
 
863
 
 
864
 
 
865
static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur)
 
866
{
 
867
  uint i,length;
 
868
  MYSQL_FIELD *field;
 
869
  putchar('|');
 
870
  mysql_field_seek(result,0);
 
871
  for (i=0 ; i < mysql_num_fields(result); i++)
 
872
  {
 
873
    field = mysql_fetch_field(result);
 
874
    length=field->max_length;
 
875
    printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");
 
876
  }
 
877
  putchar('\n');
 
878
}