diff options
Diffstat (limited to 'client/mysqlshow.c')
-rw-r--r-- | client/mysqlshow.c | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/client/mysqlshow.c b/client/mysqlshow.c new file mode 100644 index 00000000000..6cf7cdf9963 --- /dev/null +++ b/client/mysqlshow.c @@ -0,0 +1,608 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Show databases, tables or columns */ + +#define SHOW_VERSION "8.2" + +#include <global.h> +#include <my_sys.h> +#include <m_string.h> +#include "mysql.h" +#include "mysql_version.h" +#include "mysqld_error.h" +#include <signal.h> +#include <stdarg.h> +#include <getopt.h> + +static my_string host=0,password=0,user=0; +static my_bool opt_show_keys=0,opt_compress=0,opt_status=0; + +static void get_options(int *argc,char ***argv); +static uint opt_mysql_port=0; +static int list_dbs(MYSQL *mysql,const char *wild); +static int list_tables(MYSQL *mysql,const char *db,const char *table); +static int list_table_status(MYSQL *mysql,const char *db,const char *table); +static int list_fields(MYSQL *mysql,const char *db,const char *table, + const char *field); +static void print_header(const char *header,uint head_length,...); +static void print_row(const char *header,uint head_length,...); +static void print_trailer(uint length,...); +static void print_res_header(MYSQL_RES *result); +static void print_res_top(MYSQL_RES *result); +static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur); + +static const char *load_default_groups[]= { "mysqlshow","client",0 }; +static my_string opt_mysql_unix_port=0; +#include "sslopt-vars.h" + +int main(int argc, char **argv) +{ + int error; + char *wild; + MYSQL mysql; + MY_INIT(argv[0]); + load_defaults("my",load_default_groups,&argc,&argv); + get_options(&argc,&argv); + + wild=0; + if (argc && strcont(argv[argc-1],"*?%_")) + { + char *pos; + + wild=argv[--argc]; + for (pos=wild ; *pos ; pos++) + { /* Unix wildcards to sql */ + if (*pos == '*') + *pos='%'; + else if (*pos == '?') + *pos='_'; + } + } + else if (argc == 3) /* We only want one field */ + wild=argv[--argc]; + + if (argc > 2) + { + fprintf(stderr,"%s: Too many arguments\n",my_progname); + exit(1); + } + mysql_init(&mysql); + if (opt_compress) + mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); +#ifdef HAVE_OPENSSL + if (opt_use_ssl) + mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, + opt_ssl_capath); +#endif + if (!(mysql_real_connect(&mysql,host,user,password, + argv[0],opt_mysql_port,opt_mysql_unix_port, + 0))) + { + fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql)); + exit(1); + } + /* if (!(mysql_connect(&mysql,host,user,password))) */ + + + switch (argc) + { + case 0: error=list_dbs(&mysql,wild); break; + case 1: + if (opt_status) + error=list_table_status(&mysql,argv[0],wild); + else + error=list_tables(&mysql,argv[0],wild); + break; + default: + if (opt_status && ! wild) + error=list_table_status(&mysql,argv[0],argv[1]); + else + error=list_fields(&mysql,argv[0],argv[1],wild); break; + } + mysql_close(&mysql); /* Close & free connection */ + if (password) + my_free(password,MYF(0)); + my_end(0); + exit(error ? 1 : 0); + return 0; /* No compiler warnings */ +} + + +static struct option long_options[] = +{ + {"character-sets-dir", required_argument, 0, 'c'}, + {"compress", no_argument, 0, 'C'}, + {"debug", optional_argument, 0, '#'}, + {"help", no_argument, 0, '?'}, + {"host", required_argument, 0, 'h'}, + {"status", no_argument, 0, 'i'}, + {"keys", no_argument, 0, 'k'}, + {"password", optional_argument, 0, 'p'}, + {"port", required_argument, 0, 'P'}, +#ifdef __WIN__ + {"pipe", no_argument, 0, 'W'}, +#endif + {"socket", required_argument, 0, 'S'}, +#include "sslopt-longopts.h" +#ifndef DONT_ALLOW_USER_CHANGE + {"user", required_argument, 0, 'u'}, +#endif + {"version", no_argument, 0, 'V'}, + {0, 0, 0, 0} +}; + + +static void print_version(void) +{ + printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION, + MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} + +static void usage(void) +{ + print_version(); + puts("Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB"); + 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"); + puts("Shows the structure of a mysql database (databases,tables and columns)\n"); + printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname); + printf("\n\ + -#, --debug=... output debug log. Often this is 'd:t:o,filename`\n\ + -?, --help display this help and exit\n\ + -c, --character-sets-dir=...\n\ + Directory where character sets are\n\ + -C, --compress Use compression in server/client protocol\n\ + -h, --host=... connect to host\n\ + -i, --status Shows a lot of extra information about each table\n\ + -k, --keys show keys for table\n\ + -p, --password[=...] password to use when connecting to server\n\ + If password is not given it's asked from the tty.\n"); +#ifdef __WIN__ + puts("-W, --pipe Use named pipes to connect to server"); +#endif + printf("\ + -P --port=... Port number to use for connection\n\ + -S --socket=... Socket file to use for connection\n"); +#include "sslopt-usage.h" +#ifndef DONT_ALLOW_USER_CHANGE + printf("\ + -u, --user=# user for login if not current user\n"); +#endif + printf("\ + -V, --version output version information and exit\n"); + + puts("\n\ +If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\ +what\'s matched by the wildcard is shown.\n\ +If no database is given then all matching databases are shown.\n\ +If no table is given then all matching tables in database are shown\n\ +If no column is given then all matching columns and columntypes in table\n\ +are shown"); + print_defaults("my",load_default_groups); +} + + +static void +get_options(int *argc,char ***argv) +{ + int c,option_index; + my_bool tty_password=0; + + while ((c=getopt_long(*argc,*argv,"c:h:p::u:#::P:S:Ck?VWi",long_options, + &option_index)) != EOF) + { + switch(c) { + case 'C': + opt_compress=1; + break; + case 'c': + charsets_dir= optarg; + break; + case 'h': + host = optarg; + break; + case 'i': + opt_status=1; + break; + case 'k': + opt_show_keys=1; + break; + case 'p': + if (optarg) + { + my_free(password,MYF(MY_ALLOW_ZERO_PTR)); + password=my_strdup(optarg,MYF(MY_FAE)); + while (*optarg) *optarg++= 'x'; /* Destroy argument */ + } + else + tty_password=1; + break; +#ifndef DONT_ALLOW_USER_CHANGE + case 'u': + user=optarg; + break; +#endif + case 'P': + opt_mysql_port= (unsigned int) atoi(optarg); + break; + case 'S': + opt_mysql_unix_port= optarg; + break; + case 'W': +#ifdef __WIN__ + opt_mysql_unix_port=MYSQL_NAMEDPIPE; +#endif + break; +#include "sslopt-case.h" + case '#': + DBUG_PUSH(optarg ? optarg : "d:t:o"); + break; + case 'V': + print_version(); + exit(0); + break; + default: + fprintf(stderr,"Illegal option character '%c'\n",opterr); + /* Fall throught */ + case '?': + case 'I': /* Info */ + usage(); + exit(0); + } + } + (*argc)-=optind; + (*argv)+=optind; + if (tty_password) + password=get_tty_password(NullS); + return; +} + + +static int +list_dbs(MYSQL *mysql,const char *wild) +{ + const char *header; + uint length; + MYSQL_FIELD *field; + MYSQL_RES *result; + MYSQL_ROW row; + + if (!(result=mysql_list_dbs(mysql,wild))) + { + fprintf(stderr,"%s: Cannot list databases: %s\n",my_progname, + mysql_error(mysql)); + return 1; + } + if (wild) + printf("Wildcard: %s\n",wild); + + header="Databases"; + length=strlen(header); + field=mysql_fetch_field(result); + if (length < field->max_length) + length=field->max_length; + + print_header(header,length,NullS); + while ((row = mysql_fetch_row(result))) + print_row(row[0],length,0); + print_trailer(length,0); + mysql_free_result(result); + return 0; +} + + +static int +list_tables(MYSQL *mysql,const char *db,const char *table) +{ + const char *header; + uint head_length; + MYSQL_FIELD *field; + MYSQL_RES *result; + MYSQL_ROW row; + + if (mysql_select_db(mysql,db)) + { + fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname,db, + mysql_error(mysql)); + return 1; + } + if (!(result=mysql_list_tables(mysql,table))) + { + fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db, + mysql_error(mysql)); + exit(1); + } + printf("Database: %s",db); + if (table) + printf(" Wildcard: %s",table); + putchar('\n'); + + header="Tables"; + head_length=strlen(header); + field=mysql_fetch_field(result); + if (head_length < field->max_length) + head_length=field->max_length; + + print_header(header,head_length,NullS); + while ((row = mysql_fetch_row(result))) + print_row(row[0],head_length,0); + print_trailer(head_length,0); + mysql_free_result(result); + return 0; +} + +static int +list_table_status(MYSQL *mysql,const char *db,const char *wild) +{ + char query[1024],*end; + MYSQL_RES *result; + MYSQL_ROW row; + + end=strxmov(query,"show table status from ",db,NullS); + if (wild && wild[0]) + strxmov(end," like '",wild,"'",NullS); + if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) + { + fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n", + my_progname,db,wild ? wild : "",mysql_error(mysql)); + if (mysql_errno(mysql) == ER_PARSE_ERROR) + fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n"); + return 1; + } + + printf("Database: %s",db); + if (wild) + printf(" Wildcard: %s",wild); + putchar('\n'); + + print_res_header(result); + while ((row=mysql_fetch_row(result))) + print_res_row(result,row); + print_res_top(result); + mysql_free_result(result); + return 0; +} + +/* +** list fields uses field interface as an example of how to parse +** a MYSQL FIELD +*/ + +static int +list_fields(MYSQL *mysql,const char *db,const char *table, + const char *wild) +{ + char query[1024],*end; + MYSQL_RES *result; + MYSQL_ROW row; + + if (mysql_select_db(mysql,db)) + { + fprintf(stderr,"%s: Cannot connect to db: %s: %s\n",my_progname,db, + mysql_error(mysql)); + return 1; + } + end=strmov(strmov(query,"show columns from "),table); + if (wild && wild[0]) + strxmov(end," like '",wild,"'",NullS); + if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) + { + fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n", + my_progname,db,table,mysql_error(mysql)); + return 1; + } + + printf("Database: %s Table: %s Rows: %lu", db,table, + (ulong) mysql->extra_info); + if (wild && wild[0]) + printf(" Wildcard: %s",wild); + putchar('\n'); + + print_res_header(result); + while ((row=mysql_fetch_row(result))) + print_res_row(result,row); + print_res_top(result); + if (opt_show_keys) + { + end=strmov(strmov(query,"show keys from "),table); + if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) + { + fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n", + my_progname,db,table,mysql_error(mysql)); + return 1; + } + if (mysql_num_rows(result)) + { + print_res_header(result); + while ((row=mysql_fetch_row(result))) + print_res_row(result,row); + print_res_top(result); + } + else + puts("Table has no keys"); + } + mysql_free_result(result); + return 0; +} + + +/***************************************************************************** +** General functions to print a nice ascii-table from data +*****************************************************************************/ + +static void +print_header(const char *header,uint head_length,...) +{ + va_list args; + uint length,i,str_length,pre_space; + const char *field; + + va_start(args,head_length); + putchar('+'); + field=header; length=head_length; + for (;;) + { + for (i=0 ; i < length+2 ; i++) + putchar('-'); + putchar('+'); + if (!(field=va_arg(args,my_string))) + break; + length=va_arg(args,uint); + } + va_end(args); + putchar('\n'); + + va_start(args,head_length); + field=header; length=head_length; + putchar('|'); + for (;;) + { + str_length=strlen(field); + if (str_length > length) + str_length=length+1; + pre_space=(uint) (((int) length-(int) str_length)/2)+1; + for (i=0 ; i < pre_space ; i++) + putchar(' '); + for (i = 0 ; i < str_length ; i++) + putchar(field[i]); + length=length+2-str_length-pre_space; + for (i=0 ; i < length ; i++) + putchar(' '); + putchar('|'); + if (!(field=va_arg(args,my_string))) + break; + length=va_arg(args,uint); + } + va_end(args); + putchar('\n'); + + va_start(args,head_length); + putchar('+'); + field=header; length=head_length; + for (;;) + { + for (i=0 ; i < length+2 ; i++) + putchar('-'); + putchar('+'); + if (!(field=va_arg(args,my_string))) + break; + length=va_arg(args,uint); + } + va_end(args); + putchar('\n'); +} + + +static void +print_row(const char *header,uint head_length,...) +{ + va_list args; + const char *field; + uint i,length,field_length; + + va_start(args,head_length); + field=header; length=head_length; + for (;;) + { + putchar('|'); + putchar(' '); + fputs(field,stdout); + field_length=strlen(field); + for (i=field_length ; i <= length ; i++) + putchar(' '); + if (!(field=va_arg(args,my_string))) + break; + length=va_arg(args,uint); + } + va_end(args); + putchar('|'); + putchar('\n'); +} + + +static void +print_trailer(uint head_length,...) +{ + va_list args; + uint length,i; + + va_start(args,head_length); + length=head_length; + putchar('+'); + for (;;) + { + for (i=0 ; i < length+2 ; i++) + putchar('-'); + putchar('+'); + if (!(length=va_arg(args,uint))) + break; + } + va_end(args); + putchar('\n'); +} + + +static void print_res_header(MYSQL_RES *result) +{ + MYSQL_FIELD *field; + + print_res_top(result); + mysql_field_seek(result,0); + putchar('|'); + while ((field = mysql_fetch_field(result))) + { + printf(" %-*s|",field->max_length+1,field->name); + } + putchar('\n'); + print_res_top(result); +} + + +static void print_res_top(MYSQL_RES *result) +{ + uint i,length; + MYSQL_FIELD *field; + + putchar('+'); + mysql_field_seek(result,0); + while((field = mysql_fetch_field(result))) + { + if ((length=strlen(field->name)) > field->max_length) + field->max_length=length; + else + length=field->max_length; + for (i=length+2 ; i--> 0 ; ) + putchar('-'); + putchar('+'); + } + putchar('\n'); +} + + +static void print_res_row(MYSQL_RES *result,MYSQL_ROW cur) +{ + uint i,length; + MYSQL_FIELD *field; + putchar('|'); + mysql_field_seek(result,0); + for (i=0 ; i < mysql_num_fields(result); i++) + { + field = mysql_fetch_field(result); + length=field->max_length; + printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : ""); + } + putchar('\n'); +} |