2002-04-24 14:23:32 +02:00
/* Copyright (C) 2000-2002 MySQL AB
2001-12-06 13:10:51 +01:00
2000-07-31 21:29:14 +02:00
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 .
2001-12-06 13:10:51 +01:00
2000-07-31 21:29:14 +02:00
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 .
2001-12-06 13:10:51 +01:00
2000-07-31 21:29:14 +02:00
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 */
/* mysql command tool
* Commands compatible with mSQL by David J . Hughes
*
* Written by :
* Michael ' Monty ' Widenius
2002-04-03 12:36:01 +02:00
* Andi Gutmans < andi @ zend . com >
* Zeev Suraski < zeev @ zend . com >
* Jani Tolonen < jani @ mysql . com >
* Matt Wagner < matt @ mysql . com >
* Jeremy Cole < jcole @ mysql . com >
* Tonu Samuel < tonu @ mysql . com >
* Harrison Fisk < hcfisk @ buffalo . edu >
2000-07-31 21:29:14 +02:00
*
* */
2001-09-12 22:53:31 +02:00
# include "client_priv.h"
2000-07-31 21:29:14 +02:00
# include <m_ctype.h>
2002-04-02 19:29:53 +02:00
# include <stdarg.h>
2000-07-31 21:29:14 +02:00
# include <my_dir.h>
# ifndef __GNU_LIBRARY__
2000-11-17 13:33:29 +01:00
# define __GNU_LIBRARY__ // Skip warnings in getopt.h
2000-07-31 21:29:14 +02:00
# endif
# include "my_readline.h"
# include <signal.h>
2001-08-26 21:34:52 +02:00
# include <violite.h>
2000-07-31 21:29:14 +02:00
2002-10-02 16:55:12 +02:00
const char * VER = " 13.0 " ;
2000-11-28 03:47:47 +01:00
2001-02-02 02:47:06 +01:00
/* Don't try to make a nice table if the data is too big */
# define MAX_COLUMN_LENGTH 1024
2000-11-17 13:33:29 +01:00
gptr sql_alloc ( unsigned size ) ; // Don't use mysqld alloc for these
2000-07-31 21:29:14 +02:00
void sql_element_free ( void * ptr ) ;
# include "sql_string.h"
extern " C " {
# if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
# include <curses.h>
# include <term.h>
# else
# if defined(HAVE_TERMIOS_H)
# include <termios.h>
# include <unistd.h>
# elif defined(HAVE_TERMBITS_H)
# include <termbits.h>
# elif defined(HAVE_ASM_TERMBITS_H) && (!defined __GLIBC__ || !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ > 0))
2000-11-17 13:33:29 +01:00
# include <asm/termbits.h> // Standard linux
2000-07-31 21:29:14 +02:00
# endif
# undef VOID
# if defined(HAVE_TERMCAP_H)
# include <termcap.h>
# else
# ifdef HAVE_CURSES_H
# include <curses.h>
# endif
2000-11-17 13:33:29 +01:00
# undef SYSV // hack to avoid syntax error
2000-07-31 21:29:14 +02:00
# ifdef HAVE_TERM_H
# include <term.h>
# endif
# endif
# endif
2000-11-17 13:33:29 +01:00
# undef bcmp // Fix problem with new readline
2001-08-22 00:45:07 +02:00
# if defined( __WIN__) || defined(OS2)
2000-07-31 21:29:14 +02:00
# include <conio.h>
# else
# include <readline/readline.h>
# define HAVE_READLINE
# endif
//int vidattr(long unsigned int attrs); // Was missing in sun curses
}
# if !defined(HAVE_VIDATTR)
# undef vidattr
2000-11-17 13:33:29 +01:00
# define vidattr(A) {} // Can't get this to work
2000-07-31 21:29:14 +02:00
# endif
2002-10-08 21:28:24 +02:00
# ifdef FN_NO_CASE_SENCE
# define cmp_database(A,B) my_strcasecmp(system_charset_info, (A), (B))
2000-07-31 21:29:14 +02:00
# else
# define cmp_database(A,B) strcmp((A),(B))
# endif
# include "completion_hash.h"
2002-04-03 12:36:01 +02:00
# define PROMPT_CHAR '\\'
2000-07-31 21:29:14 +02:00
typedef struct st_status
{
int exit_status ;
ulong query_start_line ;
char * file_name ;
LINE_BUFFER * line_buff ;
bool batch , add_to_history ;
} STATUS ;
static HashTable ht ;
2002-08-24 01:08:10 +02:00
static char * * defaults_argv ;
2000-07-31 21:29:14 +02:00
enum enum_info_type { INFO_INFO , INFO_ERROR , INFO_RESULT } ;
typedef enum enum_info_type INFO_TYPE ;
static MYSQL mysql ; /* The connection */
2002-04-02 19:29:53 +02:00
static my_bool info_flag = 0 , ignore_errors = 0 , wait_flag = 0 , quick = 0 ,
connected = 0 , opt_raw_data = 0 , unbuffered = 0 , output_tables = 0 ,
2002-04-16 10:39:03 +02:00
rehash = 1 , skip_updates = 0 , safe_updates = 0 , one_database = 0 ,
2002-04-03 12:36:01 +02:00
opt_compress = 0 , using_opt_local_infile = 0 ,
2002-04-02 19:29:53 +02:00
vertical = 0 , line_numbers = 1 , column_names = 1 , opt_html = 0 ,
opt_xml = 0 , opt_nopager = 1 , opt_outfile = 0 , named_cmds = 0 ,
2002-04-03 14:44:20 +02:00
tty_password = 0 , opt_nobeep = 0 ;
2002-04-03 12:36:01 +02:00
static uint verbose = 0 , opt_silent = 0 , opt_mysql_port = 0 , opt_local_infile = 0 ;
2000-07-31 21:29:14 +02:00
static my_string opt_mysql_unix_port = 0 ;
static int connect_flag = CLIENT_INTERACTIVE ;
static char * current_host , * current_db , * current_user = 0 , * opt_password = 0 ,
2002-04-03 12:36:01 +02:00
* current_prompt = 0 , * default_charset ;
2000-07-31 21:29:14 +02:00
static char * histfile ;
static String glob_buffer , old_buffer ;
2002-04-03 12:36:01 +02:00
static String processed_prompt ;
static char * full_username = 0 , * part_username = 0 , * default_prompt = 0 ;
2001-01-17 13:47:33 +01:00
static int wait_time = 5 ;
2000-07-31 21:29:14 +02:00
static STATUS status ;
2000-11-27 01:28:41 +01:00
static ulong select_limit , max_join_size , opt_connect_timeout = 0 ;
2001-11-07 01:30:34 +01:00
static char mysql_charsets_dir [ FN_REFLEN + 1 ] ;
2001-04-25 00:11:29 +02:00
static const char * xmlmeta [ ] = {
2001-04-11 13:04:03 +02:00
" & " , " & " ,
" < " , " < " ,
0 , 0
} ;
2002-04-03 12:36:01 +02:00
static const char * day_names [ ] = { " Sun " , " Mon " , " Tue " , " Wed " , " Thu " , " Fri " , " Sat " } ;
static const char * month_names [ ] = { " Jan " , " Feb " , " Mar " , " Apr " , " May " , " Jun " , " Jul " ,
" Aug " , " Sep " , " Oct " , " Nov " , " Dec " } ;
static char default_pager [ FN_REFLEN ] ;
static char pager [ FN_REFLEN ] , outfile [ FN_REFLEN ] ;
static FILE * PAGER , * OUTFILE ;
static MEM_ROOT hash_mem_root ;
static uint prompt_counter ;
2000-07-31 21:29:14 +02:00
2002-11-14 20:16:30 +01:00
# ifdef HAVE_SMEM
static char * shared_memory_base_name = 0 ;
# endif
static uint opt_protocol = 0 ;
2000-07-31 21:29:14 +02:00
# include "sslopt-vars.h"
# ifndef DBUG_OFF
const char * default_dbug_option = " d:t:o,/tmp/mysql.trace " ;
# endif
2000-11-17 13:33:29 +01:00
void tee_fprintf ( FILE * file , const char * fmt , . . . ) ;
void tee_fputs ( const char * s , FILE * file ) ;
void tee_puts ( const char * s , FILE * file ) ;
2000-11-18 16:34:15 +01:00
void tee_putc ( int c , FILE * file ) ;
2000-07-31 21:29:14 +02:00
/* The names of functions that actually do the manipulation. */
static int get_options ( int argc , char * * argv ) ;
static int com_quit ( String * str , char * ) ,
com_go ( String * str , char * ) , com_ego ( String * str , char * ) ,
2000-11-22 02:45:02 +01:00
com_print ( String * str , char * ) ,
2000-07-31 21:29:14 +02:00
com_help ( String * str , char * ) , com_clear ( String * str , char * ) ,
com_connect ( String * str , char * ) , com_status ( String * str , char * ) ,
com_use ( String * str , char * ) , com_source ( String * str , char * ) ,
2000-11-22 02:45:02 +01:00
com_rehash ( String * str , char * ) , com_tee ( String * str , char * ) ,
2002-04-03 12:36:01 +02:00
com_notee ( String * str , char * ) , com_shell ( String * str , char * ) ,
com_prompt ( String * str , char * ) ;
2000-07-31 21:29:14 +02:00
2000-11-22 02:45:02 +01:00
# ifndef __WIN__
static int com_nopager ( String * str , char * ) , com_pager ( String * str , char * ) ,
com_edit ( String * str , char * ) ;
# endif
2000-07-31 21:29:14 +02:00
static int read_lines ( bool execute_commands ) ;
static int sql_connect ( char * host , char * database , char * user , char * password ,
uint silent ) ;
static int put_info ( const char * str , INFO_TYPE info , uint error = 0 ) ;
static void safe_put_field ( const char * pos , ulong length ) ;
2001-12-14 16:43:18 +01:00
static void xmlencode_print ( const char * src , uint length ) ;
2000-11-17 13:33:29 +01:00
static void init_pager ( ) ;
static void end_pager ( ) ;
2002-06-12 16:35:04 +02:00
static int init_tee ( char * ) ;
2000-11-17 13:33:29 +01:00
static void end_tee ( ) ;
2002-04-03 12:36:01 +02:00
static const char * construct_prompt ( ) ;
static void init_username ( ) ;
static void add_int_to_prompt ( int toadd ) ;
2000-07-31 21:29:14 +02:00
/* A structure which contains information on the commands this program
can understand . */
typedef struct {
const char * name ; /* User printable name of the function. */
char cmd_char ; /* msql command character */
int ( * func ) ( String * str , char * ) ; /* Function to call to do the job. */
bool takes_params ; /* Max parameters for command */
const char * doc ; /* Documentation for this function. */
} COMMANDS ;
static COMMANDS commands [ ] = {
2002-10-28 14:44:19 +01:00
{ " help " , ' h ' , com_help , 1 , " Display this help. " } ,
{ " ? " , ' ? ' , com_help , 1 , " Synonym for `help'. " } ,
2000-11-17 13:33:29 +01:00
{ " clear " , ' c ' , com_clear , 0 , " Clear command. " } ,
2000-08-11 17:17:38 +02:00
{ " connect " , ' r ' , com_connect , 1 ,
2000-11-17 13:33:29 +01:00
" Reconnect to the server. Optional arguments are db and host. " } ,
2000-11-22 02:45:02 +01:00
# ifndef __WIN__
2000-11-17 13:33:29 +01:00
{ " edit " , ' e ' , com_edit , 0 , " Edit command with $EDITOR. " } ,
2000-11-22 02:45:02 +01:00
# endif
2000-08-11 17:17:38 +02:00
{ " ego " , ' G ' , com_ego , 0 ,
2000-11-17 13:33:29 +01:00
" Send command to mysql server, display result vertically. " } ,
{ " exit " , ' q ' , com_quit , 0 , " Exit mysql. Same as quit. " } ,
{ " go " , ' g ' , com_go , 0 , " Send command to mysql server. " } ,
# ifndef __WIN__
{ " nopager " , ' n ' , com_nopager , 0 , " Disable pager, print to stdout. " } ,
# endif
{ " notee " , ' t ' , com_notee , 0 , " Don't write into outfile. " } ,
# ifndef __WIN__
{ " pager " , ' P ' , com_pager , 1 ,
" Set PAGER [to_pager]. Print the query results via PAGER. " } ,
# endif
{ " print " , ' p ' , com_print , 0 , " Print current command. " } ,
2002-04-03 12:36:01 +02:00
{ " prompt " , ' R ' , com_prompt , 1 , " Change your mysql prompt. " } ,
2000-11-17 13:33:29 +01:00
{ " quit " , ' q ' , com_quit , 0 , " Quit mysql. " } ,
{ " rehash " , ' # ' , com_rehash , 0 , " Rebuild completion hash. " } ,
2000-07-31 21:29:14 +02:00
{ " source " , ' . ' , com_source , 1 ,
2000-11-17 13:33:29 +01:00
" Execute a SQL script file. Takes a file name as an argument. " } ,
{ " status " , ' s ' , com_status , 0 , " Get status information from the server. " } ,
2001-11-06 22:00:03 +01:00
# ifndef __WIN__
{ " system " , ' ! ' , com_shell , 1 , " Execute a system shell command. " } ,
# endif
2000-11-17 13:33:29 +01:00
{ " tee " , ' T ' , com_tee , 1 ,
" Set outfile [to_outfile]. Append everything into given outfile. " } ,
2000-08-11 17:17:38 +02:00
{ " use " , ' u ' , com_use , 1 ,
2000-11-17 13:33:29 +01:00
" Use another database. Takes database name as argument. " } ,
2000-07-31 21:29:14 +02:00
2000-11-17 13:33:29 +01:00
/* Get bash-like expansion for some commands */
2000-08-11 17:17:38 +02:00
{ " create table " , 0 , 0 , 0 , " " } ,
{ " create database " , 0 , 0 , 0 , " " } ,
{ " drop " , 0 , 0 , 0 , " " } ,
{ " select " , 0 , 0 , 0 , " " } ,
{ " insert " , 0 , 0 , 0 , " " } ,
{ " replace " , 0 , 0 , 0 , " " } ,
{ " update " , 0 , 0 , 0 , " " } ,
{ " delete " , 0 , 0 , 0 , " " } ,
{ " explain " , 0 , 0 , 0 , " " } ,
{ " show databases " , 0 , 0 , 0 , " " } ,
{ " show fields from " , 0 , 0 , 0 , " " } ,
{ " show keys from " , 0 , 0 , 0 , " " } ,
{ " show tables " , 0 , 0 , 0 , " " } ,
{ " load data from " , 0 , 0 , 0 , " " } ,
{ " alter table " , 0 , 0 , 0 , " " } ,
{ " set option " , 0 , 0 , 0 , " " } ,
{ " lock tables " , 0 , 0 , 0 , " " } ,
{ " unlock tables " , 0 , 0 , 0 , " " } ,
{ ( char * ) NULL , 0 , 0 , 0 , " " }
2000-07-31 21:29:14 +02:00
} ;
static const char * load_default_groups [ ] = { " mysql " , " client " , 0 } ;
2001-10-02 04:53:00 +02:00
static const char * server_default_groups [ ] =
{ " server " , " embedded " , " mysql_SERVER " , 0 } ;
2000-07-31 21:29:14 +02:00
# ifdef HAVE_READLINE
extern " C " void add_history ( char * command ) ; /* From readline directory */
extern " C " int read_history ( char * command ) ;
extern " C " int write_history ( char * command ) ;
static void initialize_readline ( char * name ) ;
# endif
static COMMANDS * find_command ( char * name , char cmd_name ) ;
static bool add_line ( String & buffer , char * line , char * in_string ) ;
static void remove_cntrl ( String & buffer ) ;
static void print_table_data ( MYSQL_RES * result ) ;
static void print_table_data_html ( MYSQL_RES * result ) ;
2001-04-11 13:04:03 +02:00
static void print_table_data_xml ( MYSQL_RES * result ) ;
2000-07-31 21:29:14 +02:00
static void print_tab_data ( MYSQL_RES * result ) ;
static void print_table_data_vertically ( MYSQL_RES * result ) ;
static ulong start_timer ( void ) ;
static void end_timer ( ulong start_time , char * buff ) ;
static void mysql_end_timer ( ulong start_time , char * buff ) ;
static void nice_time ( double sec , char * buff , bool part_second ) ;
static sig_handler mysql_end ( int sig ) ;
int main ( int argc , char * argv [ ] )
{
char buff [ 80 ] ;
MY_INIT ( argv [ 0 ] ) ;
DBUG_ENTER ( " main " ) ;
DBUG_PROCESS ( argv [ 0 ] ) ;
2002-04-03 12:36:01 +02:00
default_prompt = my_strdup ( getenv ( " MYSQL_PS1 " ) ?
getenv ( " MYSQL_PS1 " ) :
" mysql> " , MYF ( MY_WME ) ) ;
current_prompt = my_strdup ( default_prompt , MYF ( MY_WME ) ) ;
prompt_counter = 0 ;
2000-11-17 13:33:29 +01:00
strmov ( outfile , " \0 " ) ; // no (default) outfile, unless given at least once
strmov ( pager , " stdout " ) ; // the default, if --pager wasn't given
2001-04-17 00:45:30 +02:00
{
char * tmp = getenv ( " PAGER " ) ;
if ( tmp )
strmov ( default_pager , tmp ) ;
}
2000-07-31 21:29:14 +02:00
if ( ! isatty ( 0 ) | | ! isatty ( 1 ) )
{
status . batch = 1 ; opt_silent = 1 ;
ignore_errors = 0 ;
}
else
status . add_to_history = 1 ;
status . exit_status = 1 ;
load_defaults ( " my " , load_default_groups , & argc , & argv ) ;
2002-08-24 01:08:10 +02:00
defaults_argv = argv ;
2002-04-02 19:29:53 +02:00
if ( get_options ( argc , ( char * * ) argv ) )
2000-07-31 21:29:14 +02:00
{
2002-08-24 01:08:10 +02:00
free_defaults ( defaults_argv ) ;
2000-07-31 21:29:14 +02:00
my_end ( 0 ) ;
exit ( 1 ) ;
}
if ( status . batch & & ! status . line_buff & &
! ( status . line_buff = batch_readline_init ( max_allowed_packet + 512 , stdin ) ) )
2002-08-24 01:08:10 +02:00
{
free_defaults ( defaults_argv ) ;
2000-07-31 21:29:14 +02:00
exit ( 1 ) ;
2002-08-24 01:08:10 +02:00
}
2000-07-31 21:29:14 +02:00
glob_buffer . realloc ( 512 ) ;
2001-10-08 03:58:07 +02:00
mysql_server_init ( 0 , NULL , ( char * * ) server_default_groups ) ;
completion_hash_init ( & ht , 128 ) ;
init_alloc_root ( & hash_mem_root , 16384 , 0 ) ;
2001-09-22 16:40:57 +02:00
bzero ( ( char * ) & mysql , sizeof ( mysql ) ) ;
2000-07-31 21:29:14 +02:00
if ( sql_connect ( current_host , current_db , current_user , opt_password ,
opt_silent ) )
{
2000-09-22 00:46:26 +02:00
quick = 1 ; // Avoid history
status . exit_status = 1 ;
mysql_end ( - 1 ) ;
2000-07-31 21:29:14 +02:00
}
if ( ! status . batch )
ignore_errors = 1 ; // Don't abort monitor
signal ( SIGINT , mysql_end ) ; // Catch SIGINT to clean up
2002-03-30 16:50:20 +01:00
signal ( SIGQUIT , mysql_end ) ; // Catch SIGQUIT to clean up
2000-07-31 21:29:14 +02:00
2000-11-17 13:33:29 +01:00
/*
2002-06-11 10:20:31 +02:00
Run in interactive mode like the ingres / postgres monitor
2000-07-31 21:29:14 +02:00
*/
put_info ( " Welcome to the MySQL monitor. Commands end with ; or \\ g. " ,
INFO_INFO ) ;
sprintf ( ( char * ) glob_buffer . ptr ( ) ,
" Your MySQL connection id is %ld to server version: %s \n " ,
mysql_thread_id ( & mysql ) , mysql_get_server_info ( & mysql ) ) ;
put_info ( ( char * ) glob_buffer . ptr ( ) , INFO_INFO ) ;
# ifdef HAVE_READLINE
initialize_readline ( my_progname ) ;
2001-04-11 13:04:03 +02:00
if ( ! status . batch & & ! quick & & ! opt_html & & ! opt_xml )
2000-07-31 21:29:14 +02:00
{
2002-06-11 10:20:31 +02:00
/* read-history from file, default ~/.mysql_history*/
2000-07-31 21:29:14 +02:00
if ( getenv ( " MYSQL_HISTFILE " ) )
histfile = my_strdup ( getenv ( " MYSQL_HISTFILE " ) , MYF ( MY_WME ) ) ;
else if ( getenv ( " HOME " ) )
{
2000-08-21 23:18:32 +02:00
histfile = ( char * ) my_malloc ( ( uint ) strlen ( getenv ( " HOME " ) )
+ ( uint ) strlen ( " /.mysql_history " ) + 2 ,
2000-07-31 21:29:14 +02:00
MYF ( MY_WME ) ) ;
if ( histfile )
sprintf ( histfile , " %s/.mysql_history " , getenv ( " HOME " ) ) ;
}
if ( histfile )
{
if ( verbose )
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " Reading history-file %s \n " , histfile ) ;
2000-07-31 21:29:14 +02:00
read_history ( histfile ) ;
}
}
# endif
2002-10-28 14:44:19 +01:00
sprintf ( buff , " %s%s " ,
" Type 'help;' or ' \\ h' for help. Type ' \\ c' to clear the buffer. \n " ,
" Type 'help [[%]function name[%]]' to get help on usage of function. \n " ) ;
2000-07-31 21:29:14 +02:00
put_info ( buff , INFO_INFO ) ;
status . exit_status = read_lines ( 1 ) ; // read lines and execute them
2000-11-17 13:33:29 +01:00
if ( opt_outfile )
end_tee ( ) ;
2000-07-31 21:29:14 +02:00
mysql_end ( 0 ) ;
# ifndef _lint
DBUG_RETURN ( 0 ) ; // Keep compiler happy
# endif
}
sig_handler mysql_end ( int sig )
{
2001-09-22 16:40:57 +02:00
mysql_close ( & mysql ) ;
2000-07-31 21:29:14 +02:00
# ifdef HAVE_READLINE
2001-04-11 13:04:03 +02:00
if ( ! status . batch & & ! quick & & ! opt_html & & ! opt_xml )
2000-07-31 21:29:14 +02:00
{
/* write-history */
if ( verbose )
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " Writing history-file %s \n " , histfile ) ;
2000-07-31 21:29:14 +02:00
write_history ( histfile ) ;
}
batch_readline_end ( status . line_buff ) ;
completion_hash_free ( & ht ) ;
2001-10-08 03:58:07 +02:00
free_root ( & hash_mem_root , MYF ( 0 ) ) ;
2000-07-31 21:29:14 +02:00
# endif
2000-09-22 00:46:26 +02:00
if ( sig > = 0 )
put_info ( sig ? " Aborted " : " Bye " , INFO_RESULT ) ;
2000-07-31 21:29:14 +02:00
glob_buffer . free ( ) ;
old_buffer . free ( ) ;
2002-04-03 12:36:01 +02:00
processed_prompt . free ( ) ;
2000-07-31 21:29:14 +02:00
my_free ( opt_password , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
my_free ( opt_mysql_unix_port , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
my_free ( histfile , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
my_free ( current_db , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
my_free ( current_host , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
my_free ( current_user , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
2002-04-03 12:36:01 +02:00
my_free ( full_username , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
my_free ( part_username , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
my_free ( default_prompt , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
2002-11-14 20:16:30 +01:00
# ifdef HAVE_SMEM
my_free ( shared_memory_base_name , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
# endif
2002-04-03 12:36:01 +02:00
my_free ( current_prompt , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
2001-10-02 04:53:00 +02:00
mysql_server_end ( ) ;
2002-08-24 01:08:10 +02:00
free_defaults ( defaults_argv ) ;
2000-07-31 21:29:14 +02:00
my_end ( info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0 ) ;
exit ( status . exit_status ) ;
}
2002-04-02 19:29:53 +02:00
static struct my_option my_long_options [ ] =
2000-07-31 21:29:14 +02:00
{
2002-04-02 19:29:53 +02:00
{ " help " , ' ? ' , " Display this help and exit. " , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 ,
0 , 0 , 0 , 0 , 0 } ,
{ " auto-rehash " , OPT_AUTO_REHASH ,
" Enable automatic rehashing. One doesn't need to use 'rehash' to get table and field completion, but startup and reconnecting may take a longer time. Disable with --disable-auto-rehash. " ,
2002-06-11 10:20:31 +02:00
( gptr * ) & rehash , ( gptr * ) & rehash , 0 , GET_BOOL , NO_ARG , 1 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " no-auto-rehash " , ' A ' ,
2002-06-01 10:46:06 +02:00
" No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead. " ,
2002-04-02 19:29:53 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " batch " , ' B ' ,
" Print results with a tab as separator, each row on new line. Doesn't use history file. " , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " character-sets-dir " , OPT_CHARSETS_DIR ,
" Directory where character sets are. " , ( gptr * ) & charsets_dir ,
( gptr * ) & charsets_dir , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-18 12:53:28 +02:00
{ " default-character-set " , OPT_DEFAULT_CHARSET ,
" Set the default character set. " , ( gptr * ) & default_charset ,
( gptr * ) & default_charset , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " compress " , ' C ' , " Use compression in server/client protocol. " ,
( gptr * ) & opt_compress , ( gptr * ) & opt_compress , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 ,
0 , 0 , 0 } ,
2000-07-31 21:29:14 +02:00
# ifndef DBUG_OFF
2002-04-02 19:29:53 +02:00
{ " debug " , ' # ' , " Output debug log. " , ( gptr * ) & default_dbug_option ,
( gptr * ) & default_dbug_option , 0 , GET_STR , OPT_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
2002-05-14 20:41:55 +02:00
{ " database " , ' D ' , " Database to use. " , ( gptr * ) & current_db ,
2002-05-15 19:24:00 +02:00
( gptr * ) & current_db , 0 , GET_STR_ALLOC , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " execute " , ' e ' , " Execute command and quit. (Output like with --batch). " , 0 ,
0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " vertical " , ' E ' , " Print the output of a query (rows) vertically. " ,
( gptr * ) & vertical , ( gptr * ) & vertical , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 ,
0 } ,
{ " force " , ' f ' , " Continue even if we get an sql error. " ,
( gptr * ) & ignore_errors , ( gptr * ) & ignore_errors , 0 , GET_BOOL , NO_ARG , 0 , 0 ,
0 , 0 , 0 , 0 } ,
2002-05-24 13:06:58 +02:00
{ " no-named-commands " , ' g ' ,
2002-06-01 10:46:06 +02:00
" Named commands are disabled. Use \\ * form only, or use named commands only in the beginning of a line ending with a semicolon (;) Since version 10.9 the client now starts with this option ENABLED by default! Disable with '-G'. Long format commands still work from the first line. WARNING: option deprecated; use --disable-named-commands instead. " ,
2002-04-02 19:29:53 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " named-commands " , ' G ' ,
2002-05-24 13:06:58 +02:00
" Enable named commands. Named commands mean this program's internal commands; see mysql> help . When enabled, the named commands can be used from any line of the query, otherwise only from the first line, before an enter. Disable with --disable-named-commands. This option is disabled by default. " ,
2002-04-02 19:29:53 +02:00
( gptr * ) & named_cmds , ( gptr * ) & named_cmds , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 ,
0 , 0 } ,
2002-09-30 19:35:21 +02:00
{ " ignore-spaces " , ' i ' , " Ignore space after function names. " , 0 , 0 , 0 ,
2002-04-02 19:29:53 +02:00
GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-03 12:36:01 +02:00
{ " local-infile " , OPT_LOCAL_INFILE , " Enable/disable LOAD DATA LOCAL INFILE. " ,
2002-09-22 09:35:15 +02:00
( gptr * ) & opt_local_infile ,
( gptr * ) & opt_local_infile , 0 , GET_BOOL , OPT_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-05-14 20:41:55 +02:00
{ " no-beep " , ' b ' , " Turn off beep on error. " , ( gptr * ) & opt_nobeep ,
( gptr * ) & opt_nobeep , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-05-11 13:36:34 +02:00
{ " host " , ' h ' , " Connect to host. " , ( gptr * ) & current_host ,
2002-05-15 19:24:00 +02:00
( gptr * ) & current_host , 0 , GET_STR_ALLOC , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " html " , ' H ' , " Produce HTML output. " , ( gptr * ) & opt_html , ( gptr * ) & opt_html ,
0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " xml " , ' X ' , " Produce XML output " , ( gptr * ) & opt_xml , ( gptr * ) & opt_xml , 0 ,
GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " line-numbers " , OPT_LINE_NUMBERS , " Write line numbers for errors. " ,
( gptr * ) & line_numbers , ( gptr * ) & line_numbers , 0 , GET_BOOL ,
2002-06-11 10:20:31 +02:00
NO_ARG , 1 , 0 , 0 , 0 , 0 , 0 } ,
2002-06-01 10:46:06 +02:00
{ " skip-line-numbers " , ' L ' , " Don't write line number for errors. WARNING: -L is deprecated, use long version of this option instead. " , 0 , 0 , 0 , GET_NO_ARG ,
2002-04-02 19:29:53 +02:00
NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# ifndef __WIN__
{ " no-pager " , OPT_NOPAGER ,
2002-06-01 10:46:06 +02:00
" Disable pager and print to stdout. See interactive help ( \\ h) also. WARNING: option deprecated; use --disable-pager instead. " ,
2002-04-02 19:29:53 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2000-07-31 21:29:14 +02:00
# endif
2002-06-01 10:46:06 +02:00
{ " no-tee " , OPT_NOTEE , " Disable outfile. See interactive help ( \\ h) also. WARNING: option deprecated; use --disable-tee instead " , 0 , 0 , 0 , GET_NO_ARG ,
2002-04-02 19:29:53 +02:00
NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " unbuffered " , ' n ' , " Flush buffer after each query. " , ( gptr * ) & unbuffered ,
( gptr * ) & unbuffered , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " column-names " , OPT_COLUMN_NAMES , " Write column names in results. " ,
( gptr * ) & column_names , ( gptr * ) & column_names , 0 , GET_BOOL ,
2002-05-28 13:47:51 +02:00
NO_ARG , 1 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " skip-column-names " , ' N ' ,
2002-06-01 10:46:06 +02:00
" Don't write column names in results. WARNING: -N is deprecated, use long version of this options instead. " ,
2002-04-02 19:29:53 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " set-variable " , ' O ' ,
2002-06-01 10:46:06 +02:00
" Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value. " ,
2002-04-02 19:29:53 +02:00
0 , 0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " one-database " , ' o ' ,
" Only update the default database. This is useful for skipping updates to other database in the update log. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2000-11-17 13:33:29 +01:00
# ifndef __WIN__
2002-04-02 19:29:53 +02:00
{ " pager " , OPT_PAGER ,
" Pager to use to display results. If you don't supply an option the default pager is taken from your ENV variable PAGER. Valid pagers are less, more, cat [> filename], etc. See interactive help ( \\ h) also. This option does not work in batch mode. " ,
0 , 0 , 0 , GET_STR , OPT_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2000-11-17 13:33:29 +01:00
# endif
2002-04-02 19:29:53 +02:00
{ " password " , ' p ' ,
" Password to use when connecting to server. If password is not given it's asked from the tty. " ,
0 , 0 , 0 , GET_STR , OPT_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2000-07-31 21:29:14 +02:00
# ifdef __WIN__
2002-04-02 19:29:53 +02:00
{ " pipe " , ' W ' , " Use named pipes to connect to server. " , 0 , 0 , 0 , GET_NO_ARG ,
NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2000-07-31 21:29:14 +02:00
# endif
2002-05-11 13:36:34 +02:00
{ " port " , ' P ' , " Port number to use for connection. " , ( gptr * ) & opt_mysql_port ,
( gptr * ) & opt_mysql_port , 0 , GET_UINT , REQUIRED_ARG , MYSQL_PORT , 0 , 0 , 0 , 0 ,
0 } ,
2002-05-14 20:41:55 +02:00
{ " prompt " , OPT_PROMPT , " Set the mysql prompt to this value. " ,
2002-05-15 19:24:00 +02:00
( gptr * ) & current_prompt , ( gptr * ) & current_prompt , 0 , GET_STR_ALLOC ,
2002-05-14 20:41:55 +02:00
REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-11-14 20:16:30 +01:00
{ " protocol " , OPT_MYSQL_PROTOCOL , " The protocol of connection (tcp,socket,pipe,memory) " ,
0 , 0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " quick " , ' q ' ,
" Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file. " ,
( gptr * ) & quick , ( gptr * ) & quick , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " raw " , ' r ' , " Write fields without conversion. Used with --batch " ,
( gptr * ) & opt_raw_data , ( gptr * ) & opt_raw_data , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 ,
0 , 0 , 0 } ,
{ " silent " , ' s ' , " Be more silent. " , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 ,
0 , 0 } ,
2002-11-14 20:16:30 +01:00
# ifdef HAVE_SMEM
{ " shared_memory_base_name " , OPT_SHARED_MEMORY_BASE_NAME ,
" Base name of shared memory " , ( gptr * ) & shared_memory_base_name , ( gptr * ) & shared_memory_base_name ,
0 , GET_STR_ALLOC , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
2002-04-02 19:29:53 +02:00
{ " socket " , ' S ' , " Socket file to use for connection. " ,
2002-05-15 19:24:00 +02:00
( gptr * ) & opt_mysql_unix_port , ( gptr * ) & opt_mysql_unix_port , 0 , GET_STR_ALLOC ,
2002-05-14 20:41:55 +02:00
REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2000-07-31 21:29:14 +02:00
# include "sslopt-longopts.h"
2002-04-02 19:29:53 +02:00
{ " table " , ' t ' , " Output in table format. " , ( gptr * ) & output_tables ,
( gptr * ) & output_tables , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " debug-info " , ' T ' , " Print some debug info at exit. " , ( gptr * ) & info_flag ,
( gptr * ) & info_flag , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " tee " , OPT_TEE ,
" Append everything into outfile. See interactive help ( \\ h) also. Does not work in batch mode. " ,
0 , 0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2000-07-31 21:29:14 +02:00
# ifndef DONT_ALLOW_USER_CHANGE
2002-04-02 19:29:53 +02:00
{ " user " , ' u ' , " User for login if not current user. " , ( gptr * ) & current_user ,
2002-05-15 19:24:00 +02:00
( gptr * ) & current_user , 0 , GET_STR_ALLOC , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2000-07-31 21:29:14 +02:00
# endif
2002-04-02 19:29:53 +02:00
{ " safe-updates " , ' U ' , " Only allow UPDATE and DELETE that uses keys. " ,
( gptr * ) & safe_updates , ( gptr * ) & safe_updates , 0 , GET_BOOL , OPT_ARG , 0 , 0 ,
0 , 0 , 0 , 0 } ,
2002-10-04 16:18:41 +02:00
{ " i-am-a-dummy " , ' U ' , " Synonym for option --safe-updates, -U. " ,
( gptr * ) & safe_updates , ( gptr * ) & safe_updates , 0 , GET_BOOL , OPT_ARG , 0 , 0 ,
0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " verbose " , ' v ' , " Write more. (-v -v -v gives the table output format) " , 0 ,
0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " version " , ' V ' , " Output version information and exit. " , 0 , 0 , 0 ,
GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " wait " , ' w ' , " Wait and retry if connection is down. " , 0 , 0 , 0 , GET_NO_ARG ,
NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " connect_timeout " , OPT_CONNECT_TIMEOUT , " " , ( gptr * ) & opt_connect_timeout ,
2002-05-11 13:36:34 +02:00
( gptr * ) & opt_connect_timeout , 0 , GET_ULONG , REQUIRED_ARG , 0 , 0 , 3600 * 12 , 0 ,
2002-04-02 19:29:53 +02:00
0 , 1 } ,
{ " max_allowed_packet " , OPT_MAX_ALLOWED_PACKET , " " ,
2002-05-11 13:36:34 +02:00
( gptr * ) & max_allowed_packet , ( gptr * ) & max_allowed_packet , 0 , GET_ULONG ,
2002-04-02 19:29:53 +02:00
REQUIRED_ARG , 16 * 1024L * 1024L , 4096 , 512 * 1024L * 1024L , MALLOC_OVERHEAD ,
1024 , 0 } ,
{ " net_buffer_length " , OPT_NET_BUFFER_LENGTH , " " ,
2002-05-11 13:36:34 +02:00
( gptr * ) & net_buffer_length , ( gptr * ) & net_buffer_length , 0 , GET_ULONG ,
2002-04-02 19:29:53 +02:00
REQUIRED_ARG , 16384 , 1024 , 512 * 1024 * 1024L , MALLOC_OVERHEAD , 1024 , 0 } ,
{ " select_limit " , OPT_SELECT_LIMIT , " " , ( gptr * ) & select_limit ,
2002-05-11 13:36:34 +02:00
( gptr * ) & select_limit , 0 , GET_ULONG , REQUIRED_ARG , 1000L , 1 , ~ 0L , 0 , 1 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " max_join_size " , OPT_MAX_JOIN_SIZE , " " , ( gptr * ) & max_join_size ,
2002-05-11 13:36:34 +02:00
( gptr * ) & max_join_size , 0 , GET_ULONG , REQUIRED_ARG , 1000000L , 1 , ~ 0L , 0 , 1 ,
2002-04-02 19:29:53 +02:00
0 } ,
{ 0 , 0 , 0 , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 }
2000-07-31 21:29:14 +02:00
} ;
static void usage ( int version )
{
2000-11-18 16:34:15 +01:00
printf ( " %s Ver %s Distrib %s, for %s (%s) \n " ,
my_progname , VER , MYSQL_SERVER_VERSION , SYSTEM_TYPE , MACHINE_TYPE ) ;
2000-07-31 21:29:14 +02:00
if ( version )
return ;
2002-04-03 12:36:01 +02:00
printf ( " \
2002-06-11 10:20:31 +02:00
Copyright ( C ) 2002 MySQL AB \ n \
2002-04-03 12:36:01 +02:00
This software comes with ABSOLUTELY NO WARRANTY . This is free software , \ n \
and you are welcome to modify and redistribute it under the GPL license \ n " );
2000-07-31 21:29:14 +02:00
printf ( " Usage: %s [OPTIONS] [database] \n " , my_progname ) ;
2002-04-02 19:29:53 +02:00
my_print_help ( my_long_options ) ;
2002-04-03 14:44:20 +02:00
print_defaults ( " my " , load_default_groups ) ;
2002-04-02 19:29:53 +02:00
my_print_variables ( my_long_options ) ;
2000-07-31 21:29:14 +02:00
}
2002-04-02 19:29:53 +02:00
static my_bool
get_one_option ( int optid , const struct my_option * opt __attribute__ ( ( unused ) ) ,
char * argument )
2000-07-31 21:29:14 +02:00
{
2002-04-02 19:29:53 +02:00
switch ( optid ) {
2002-05-31 14:43:21 +02:00
case OPT_CHARSETS_DIR :
strmov ( mysql_charsets_dir , argument ) ;
charsets_dir = mysql_charsets_dir ;
break ;
case OPT_LOCAL_INFILE :
using_opt_local_infile = 1 ;
break ;
case OPT_TEE :
if ( argument = = disabled_my_option )
{
2000-11-17 13:33:29 +01:00
if ( opt_outfile )
end_tee ( ) ;
2002-05-31 14:43:21 +02:00
}
else
2002-06-12 16:35:04 +02:00
opt_outfile = init_tee ( argument ) ;
2002-05-31 14:43:21 +02:00
break ;
case OPT_NOTEE :
2002-06-01 10:46:06 +02:00
printf ( " WARNING: option deprecated; use --disable-tee instead. \n " ) ;
2002-05-31 14:43:21 +02:00
if ( opt_outfile )
end_tee ( ) ;
break ;
case OPT_PAGER :
2002-10-15 22:34:55 +02:00
if ( argument = = disabled_my_option )
opt_nopager = 1 ;
2002-05-31 14:43:21 +02:00
else
2002-10-15 22:34:55 +02:00
{
opt_nopager = 0 ;
if ( argument )
strmov ( pager , argument ) ;
else
strmov ( pager , default_pager ) ;
strmov ( default_pager , pager ) ;
}
2002-05-31 14:43:21 +02:00
break ;
case OPT_NOPAGER :
2002-06-01 10:46:06 +02:00
printf ( " WARNING: option deprecated; use --disable-pager instead. \n " ) ;
2002-05-31 14:43:21 +02:00
opt_nopager = 1 ;
2002-11-14 20:16:30 +01:00
case OPT_MYSQL_PROTOCOL :
{
if ( ( opt_protocol = find_type ( argument , & sql_protocol_typelib , 0 ) ) = = ~ ( ulong ) 0 )
{
fprintf ( stderr , " Unknown option to protocol: %s \n " , argument ) ;
exit ( 1 ) ;
}
break ;
}
2002-05-31 14:43:21 +02:00
break ;
case ' A ' :
rehash = 0 ;
break ;
case ' N ' :
column_names = 0 ;
break ;
case ' e ' :
status . batch = 1 ;
status . add_to_history = 0 ;
batch_readline_end ( status . line_buff ) ; // If multiple -e
if ( ! ( status . line_buff = batch_readline_command ( argument ) ) )
return 1 ;
ignore_errors = 0 ;
break ;
case ' o ' :
if ( argument = = disabled_my_option )
one_database = 0 ;
else
one_database = skip_updates = 1 ;
break ;
case ' p ' :
if ( argument = = disabled_my_option )
argument = ( char * ) " " ; // Don't require password
if ( argument )
{
char * start = argument ;
my_free ( opt_password , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
opt_password = my_strdup ( argument , MYF ( MY_FAE ) ) ;
while ( * argument ) * argument + + = ' x ' ; // Destroy argument
if ( * start )
start [ 1 ] = 0 ;
}
else
tty_password = 1 ;
break ;
case ' # ' :
DBUG_PUSH ( argument ? argument : default_dbug_option ) ;
info_flag = 1 ;
break ;
case ' s ' :
if ( argument = = disabled_my_option )
opt_silent = 0 ;
else
opt_silent + + ;
break ;
case ' v ' :
if ( argument = = disabled_my_option )
verbose = 0 ;
else
verbose + + ;
break ;
case ' B ' :
if ( ! status . batch )
{
status . batch = 1 ;
status . add_to_history = 0 ;
opt_silent + + ; // more silent
}
break ;
case ' W ' :
2000-07-31 21:29:14 +02:00
# ifdef __WIN__
2002-11-14 20:16:30 +01:00
opt_protocol = MYSQL_PROTOCOL_PIPE ;
2000-07-31 21:29:14 +02:00
# endif
2002-05-31 14:43:21 +02:00
break ;
2002-09-20 13:05:18 +02:00
# include <sslopt-case.h>
2002-05-31 14:43:21 +02:00
case ' V ' :
usage ( 1 ) ;
exit ( 0 ) ;
case ' I ' :
case ' ? ' :
usage ( 0 ) ;
exit ( 0 ) ;
2000-07-31 21:29:14 +02:00
}
2002-04-02 19:29:53 +02:00
return 0 ;
}
static int get_options ( int argc , char * * argv )
{
char * tmp , * pagpoint ;
int ho_error ;
tmp = ( char * ) getenv ( " MYSQL_HOST " ) ;
if ( tmp )
current_host = my_strdup ( tmp , MYF ( MY_WME ) ) ;
pagpoint = getenv ( " PAGER " ) ;
if ( ! ( ( char * ) ( pagpoint ) ) )
{
strmov ( pager , " stdout " ) ;
opt_nopager = 1 ;
}
else
strmov ( pager , pagpoint ) ;
strmov ( default_pager , pager ) ;
if ( ( ho_error = handle_options ( & argc , & argv , my_long_options , get_one_option ) ) )
2002-05-29 14:07:30 +02:00
exit ( ho_error ) ;
2002-04-02 19:29:53 +02:00
2000-11-17 13:33:29 +01:00
if ( status . batch ) /* disable pager and outfile in this case */
{
strmov ( default_pager , " stdout " ) ;
strmov ( pager , " stdout " ) ;
2002-04-02 19:29:53 +02:00
opt_nopager = 1 ;
opt_outfile = 0 ;
2002-08-06 21:51:43 +02:00
connect_flag = 0 ; /* Not in interactive mode */
2000-11-17 13:33:29 +01:00
}
2000-07-31 21:29:14 +02:00
if ( default_charset )
{
if ( set_default_charset_by_name ( default_charset , MYF ( MY_WME ) ) )
exit ( 1 ) ;
}
if ( argc > 1 )
{
usage ( 0 ) ;
exit ( 1 ) ;
}
if ( argc = = 1 )
{
2002-04-02 19:29:53 +02:00
my_free ( current_db , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
current_db = my_strdup ( * argv , MYF ( MY_WME ) ) ;
2000-07-31 21:29:14 +02:00
}
if ( tty_password )
2002-04-02 19:29:53 +02:00
opt_password = get_tty_password ( NullS ) ;
2000-07-31 21:29:14 +02:00
return ( 0 ) ;
}
static int read_lines ( bool execute_commands )
{
2001-08-22 00:45:07 +02:00
# if defined( __WIN__) || defined(OS2)
2000-07-31 21:29:14 +02:00
char linebuffer [ 254 ] ;
# endif
char * line ;
char in_string = 0 ;
ulong line_number = 0 ;
COMMANDS * com ;
status . exit_status = 1 ;
for ( ; ; )
{
if ( status . batch | | ! execute_commands )
{
line = batch_readline ( status . line_buff ) ;
line_number + + ;
if ( ! glob_buffer . length ( ) )
status . query_start_line = line_number ;
}
else
2000-11-17 13:33:29 +01:00
{
2001-08-22 00:45:07 +02:00
# if defined( __WIN__) || defined(OS2)
2000-11-22 02:45:02 +01:00
if ( opt_outfile & & glob_buffer . is_empty ( ) )
fflush ( OUTFILE ) ;
2002-04-03 12:36:01 +02:00
tee_fputs ( glob_buffer . is_empty ( ) ? construct_prompt ( ) :
2000-11-22 02:45:02 +01:00
! in_string ? " -> " :
in_string = = ' \' ' ?
" '> " : " \" > " , stdout ) ;
linebuffer [ 0 ] = ( char ) sizeof ( linebuffer ) ;
line = _cgets ( linebuffer ) ;
# else
2000-11-17 20:36:47 +01:00
if ( opt_outfile )
{
if ( glob_buffer . is_empty ( ) )
fflush ( OUTFILE ) ;
2002-04-03 12:36:01 +02:00
fputs ( glob_buffer . is_empty ( ) ? construct_prompt ( ) :
2000-11-17 20:36:47 +01:00
! in_string ? " -> " :
in_string = = ' \' ' ?
" '> " : " \" > " , OUTFILE ) ;
}
2002-04-03 12:36:01 +02:00
line = readline ( ( char * ) ( glob_buffer . is_empty ( ) ? construct_prompt ( ) :
2000-11-17 20:36:47 +01:00
! in_string ? " -> " :
in_string = = ' \' ' ?
" '> " : " \" > " ) ) ;
2000-11-20 18:56:13 +01:00
# endif
2000-11-17 20:36:47 +01:00
if ( opt_outfile )
fprintf ( OUTFILE , " %s \n " , line ) ;
2000-11-20 18:50:41 +01:00
}
2000-07-31 21:29:14 +02:00
if ( ! line ) // End of file
{
status . exit_status = 0 ;
break ;
}
if ( ! in_string & & ( line [ 0 ] = = ' # ' | |
( line [ 0 ] = = ' - ' & & line [ 1 ] = = ' - ' ) | |
line [ 0 ] = = 0 ) )
2000-08-29 18:38:32 +02:00
continue ; // Skip comment lines
2000-07-31 21:29:14 +02:00
2002-06-11 10:20:31 +02:00
/*
Check if line is a mysql command line
( We want to allow help , print and clear anywhere at line start
*/
2002-04-02 19:29:53 +02:00
if ( execute_commands & & ( named_cmds | | glob_buffer . is_empty ( ) )
2000-08-29 18:38:32 +02:00
& & ! in_string & & ( com = find_command ( line , 0 ) ) )
2000-07-31 21:29:14 +02:00
{
if ( ( * com - > func ) ( & glob_buffer , line ) > 0 )
break ;
if ( glob_buffer . is_empty ( ) ) // If buffer was emptied
in_string = 0 ;
# ifdef HAVE_READLINE
if ( status . add_to_history )
add_history ( line ) ;
# endif
continue ;
}
if ( add_line ( glob_buffer , line , & in_string ) )
break ;
}
/* if in batch mode, send last query even if it doesn't end with \g or go */
if ( ( status . batch | | ! execute_commands ) & & ! status . exit_status )
{
remove_cntrl ( glob_buffer ) ;
if ( ! glob_buffer . is_empty ( ) )
{
status . exit_status = 1 ;
if ( com_go ( & glob_buffer , line ) < = 0 )
status . exit_status = 0 ;
}
}
return status . exit_status ;
}
static COMMANDS * find_command ( char * name , char cmd_char )
{
uint len ;
char * end ;
if ( ! name )
{
len = 0 ;
end = 0 ;
}
else
{
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * name ) )
2000-07-31 21:29:14 +02:00
name + + ;
if ( strchr ( name , ' ; ' ) | | strstr ( name , " \\ g " ) )
return ( ( COMMANDS * ) 0 ) ;
if ( ( end = strcont ( name , " \t " ) ) )
{
len = ( uint ) ( end - name ) ;
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * end ) )
2000-07-31 21:29:14 +02:00
end + + ;
if ( ! * end )
end = 0 ; // no arguments to function
}
else
2000-08-21 23:18:32 +02:00
len = ( uint ) strlen ( name ) ;
2000-07-31 21:29:14 +02:00
}
for ( uint i = 0 ; commands [ i ] . name ; i + + )
{
if ( commands [ i ] . func & &
2002-03-12 18:37:58 +01:00
( ( name & &
! my_strncasecmp ( system_charset_info , name , commands [ i ] . name , len ) & &
2000-07-31 21:29:14 +02:00
! commands [ i ] . name [ len ] & &
( ! end | | ( end & & commands [ i ] . takes_params ) ) ) | |
! name & & commands [ i ] . cmd_char = = cmd_char ) )
return ( & commands [ i ] ) ;
}
return ( ( COMMANDS * ) 0 ) ;
}
static bool add_line ( String & buffer , char * line , char * in_string )
{
uchar inchar ;
char buff [ 80 ] , * pos , * out ;
COMMANDS * com ;
if ( ! line [ 0 ] & & buffer . is_empty ( ) )
return 0 ;
# ifdef HAVE_READLINE
if ( status . add_to_history & & line [ 0 ] )
add_history ( line ) ;
# endif
# ifdef USE_MB
2000-08-21 23:18:32 +02:00
char * strend = line + ( uint ) strlen ( line ) ;
2000-07-31 21:29:14 +02:00
# endif
for ( pos = out = line ; ( inchar = ( uchar ) * pos ) ; pos + + )
{
2002-03-14 17:52:48 +01:00
if ( my_isspace ( system_charset_info , inchar ) & & out = = line & &
2002-03-12 18:37:58 +01:00
buffer . is_empty ( ) )
2000-07-31 21:29:14 +02:00
continue ;
# ifdef USE_MB
int l ;
2002-03-14 17:52:48 +01:00
if ( use_mb ( system_charset_info ) & &
( l = my_ismbchar ( system_charset_info , pos , strend ) ) ) {
2000-07-31 21:29:14 +02:00
while ( l - - )
* out + + = * pos + + ;
pos - - ;
continue ;
}
# endif
if ( inchar = = ' \\ ' )
{ // mSQL or postgreSQL style command ?
if ( ! ( inchar = ( uchar ) * + + pos ) )
break ; // readline adds one '\'
2001-10-02 20:08:08 +02:00
if ( * in_string | | inchar = = ' N ' ) // \N is short for NULL
2000-07-31 21:29:14 +02:00
{ // Don't allow commands in string
* out + + = ' \\ ' ;
* out + + = ( char ) inchar ;
continue ;
}
if ( ( com = find_command ( NullS , ( char ) inchar ) ) )
{
2002-11-10 11:05:17 +01:00
const String tmp ( line , ( uint ) ( out - line ) , system_charset_info ) ;
2000-07-31 21:29:14 +02:00
buffer . append ( tmp ) ;
if ( ( * com - > func ) ( & buffer , pos - 1 ) > 0 )
return 1 ; // Quit
if ( com - > takes_params )
{
for ( pos + + ; * pos & & * pos ! = ' ; ' ; pos + + ) ; // Remove parameters
if ( ! * pos )
pos - - ;
}
out = line ;
}
else
{
sprintf ( buff , " Unknown command ' \\ %c'. " , inchar ) ;
if ( put_info ( buff , INFO_ERROR ) > 0 )
return 1 ;
* out + + = ' \\ ' ;
* out + + = ( char ) inchar ;
continue ;
}
}
else if ( inchar = = ' ; ' & & ! * in_string )
{ // ';' is end of command
if ( out ! = line )
buffer . append ( line , ( uint ) ( out - line ) ) ; // Add this line
if ( ( com = find_command ( buffer . c_ptr ( ) , 0 ) ) )
{
if ( ( * com - > func ) ( & buffer , buffer . c_ptr ( ) ) > 0 )
return 1 ; // Quit
}
else
{
int error = com_go ( & buffer , 0 ) ;
if ( error )
{
return error < 0 ? 0 : 1 ; // < 0 is not fatal
}
}
buffer . length ( 0 ) ;
out = line ;
}
else if ( ! * in_string & & ( inchar = = ' # ' | |
inchar = = ' - ' & & pos [ 1 ] = = ' - ' & &
2002-03-12 18:37:58 +01:00
my_isspace ( system_charset_info , pos [ 2 ] ) ) )
2000-07-31 21:29:14 +02:00
break ; // comment to end of line
else
{ // Add found char to buffer
if ( inchar = = * in_string )
* in_string = 0 ;
else if ( ! * in_string & & ( inchar = = ' \' ' | | inchar = = ' " ' ) )
* in_string = ( char ) inchar ;
* out + + = ( char ) inchar ;
}
}
if ( out ! = line | | ! buffer . is_empty ( ) )
{
* out + + = ' \n ' ;
uint length = ( uint ) ( out - line ) ;
if ( buffer . length ( ) + length > = buffer . alloced_length ( ) )
buffer . realloc ( buffer . length ( ) + length + IO_SIZE ) ;
if ( buffer . append ( line , length ) )
return 1 ;
}
return 0 ;
}
2002-06-11 10:20:31 +02:00
/*****************************************************************
Interface to Readline Completion
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-07-31 21:29:14 +02:00
# ifdef HAVE_READLINE
2002-11-19 15:26:53 +01:00
static char * new_command_generator ( const char * text , int ) ;
static char * * new_mysql_completion ( const char * text , int start , int end ) ;
2000-07-31 21:29:14 +02:00
2002-06-11 10:20:31 +02:00
/*
Tell the GNU Readline library how to complete . We want to try to complete
on command names if this is the first word in the line , or on filenames
if not .
*/
2000-07-31 21:29:14 +02:00
2002-11-19 15:26:53 +01:00
char * no_completion ( const char * text __attribute__ ( ( unused ) ) ,
int )
2000-07-31 21:29:14 +02:00
{
return 0 ; /* No filename completion */
}
static void initialize_readline ( char * name )
{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = name ;
/* Tell the completer that we want a crack first. */
2002-11-26 14:03:25 +01:00
# if RL_READLINE_VERSION > 0x0400
2002-11-19 15:26:53 +01:00
rl_attempted_completion_function = & new_mysql_completion ;
rl_completion_entry_function = & no_completion ;
2002-11-26 14:03:25 +01:00
# else
rl_attempted_completion_function = ( CPPFunction * ) new_mysql_completion ;
rl_completion_entry_function = ( Function * ) no_completion ;
# endif
2000-07-31 21:29:14 +02:00
}
2002-06-11 10:20:31 +02:00
/*
Attempt to complete on the contents of TEXT . START and END show the
region of TEXT that contains the word to complete . We can use the
entire line in case we want to do some simple parsing . Return the
array of matches , or NULL if there aren ' t any .
*/
2000-07-31 21:29:14 +02:00
2002-11-19 15:26:53 +01:00
static char * * new_mysql_completion ( const char * text ,
2000-07-31 21:29:14 +02:00
int start __attribute__ ( ( unused ) ) ,
int end __attribute__ ( ( unused ) ) )
{
if ( ! status . batch & & ! quick )
2002-11-26 14:03:25 +01:00
# if RL_READLINE_VERSION > 0x0400
2002-11-19 15:26:53 +01:00
return rl_completion_matches ( text , new_command_generator ) ;
2002-11-26 14:03:25 +01:00
# else
return completion_matches ( ( char * ) text , ( CPFunction * ) new_command_generator ) ;
# endif
2000-07-31 21:29:14 +02:00
else
return ( char * * ) 0 ;
}
2002-11-19 15:26:53 +01:00
static char * new_command_generator ( const char * text , int state )
2000-07-31 21:29:14 +02:00
{
static int textlen ;
char * ptr ;
static Bucket * b ;
static entry * e ;
static uint i ;
2002-06-11 10:20:31 +02:00
if ( ! state )
2000-08-21 23:18:32 +02:00
textlen = ( uint ) strlen ( text ) ;
2000-07-31 21:29:14 +02:00
2002-06-11 10:20:31 +02:00
if ( textlen > 0 )
{ /* lookup in the hash */
if ( ! state )
{
2000-07-31 21:29:14 +02:00
uint len ;
2000-08-21 23:18:32 +02:00
b = find_all_matches ( & ht , text , ( uint ) strlen ( text ) , & len ) ;
2002-06-11 10:20:31 +02:00
if ( ! b )
2000-07-31 21:29:14 +02:00
return NullS ;
e = b - > pData ;
}
2002-06-11 10:20:31 +02:00
if ( e )
{
2000-07-31 21:29:14 +02:00
ptr = strdup ( e - > str ) ;
e = e - > pNext ;
return ptr ;
}
2002-06-11 10:20:31 +02:00
}
else
{ /* traverse the entire hash, ugly but works */
2000-07-31 21:29:14 +02:00
2002-06-11 10:20:31 +02:00
if ( ! state )
{
2000-07-31 21:29:14 +02:00
/* find the first used bucket */
2002-06-11 10:20:31 +02:00
for ( i = 0 ; i < ht . nTableSize ; i + + )
{
if ( ht . arBuckets [ i ] )
{
2000-07-31 21:29:14 +02:00
b = ht . arBuckets [ i ] ;
e = b - > pData ;
break ;
}
}
}
ptr = NullS ;
2002-06-11 10:20:31 +02:00
while ( e & & ! ptr )
{ /* find valid entry in bucket */
if ( ( uint ) strlen ( e - > str ) = = b - > nKeyLength )
2000-07-31 21:29:14 +02:00
ptr = strdup ( e - > str ) ;
/* find the next used entry */
e = e - > pNext ;
2002-06-11 10:20:31 +02:00
if ( ! e )
{ /* find the next used bucket */
2000-07-31 21:29:14 +02:00
b = b - > pNext ;
2002-06-11 10:20:31 +02:00
if ( ! b )
{
for ( i + + ; i < ht . nTableSize ; i + + )
{
if ( ht . arBuckets [ i ] )
{
2000-07-31 21:29:14 +02:00
b = ht . arBuckets [ i ] ;
e = b - > pData ;
break ;
}
}
}
2002-06-11 10:20:31 +02:00
else
e = b - > pData ;
2000-07-31 21:29:14 +02:00
}
}
2002-06-11 10:20:31 +02:00
if ( ptr )
2000-07-31 21:29:14 +02:00
return ptr ;
}
return NullS ;
}
/* Build up the completion hash */
2002-04-16 10:39:03 +02:00
static void build_completion_hash ( bool rehash , bool write_info )
2000-07-31 21:29:14 +02:00
{
COMMANDS * cmd = commands ;
2001-10-08 03:58:07 +02:00
MYSQL_RES * databases = 0 , * tables = 0 ;
MYSQL_RES * fields ;
2000-07-31 21:29:14 +02:00
static char * * * field_names = 0 ;
MYSQL_ROW database_row , table_row ;
MYSQL_FIELD * sql_field ;
char buf [ NAME_LEN * 2 + 2 ] ; // table name plus field name plus 2
int i , j , num_fields ;
DBUG_ENTER ( " build_completion_hash " ) ;
2000-09-22 00:46:26 +02:00
if ( status . batch | | quick | | ! current_db )
2000-07-31 21:29:14 +02:00
DBUG_VOID_RETURN ; // We don't need completion in batches
if ( tables )
{
mysql_free_result ( tables ) ;
tables = 0 ;
}
/* hash SQL commands */
while ( cmd - > name ) {
add_word ( & ht , ( char * ) cmd - > name ) ;
cmd + + ;
}
2002-04-16 10:39:03 +02:00
if ( ! rehash )
2000-07-31 21:29:14 +02:00
DBUG_VOID_RETURN ;
2001-10-08 03:58:07 +02:00
/* Free old used memory */
if ( field_names )
field_names = 0 ;
completion_hash_clean ( & ht ) ;
free_root ( & hash_mem_root , MYF ( 0 ) ) ;
2000-07-31 21:29:14 +02:00
/* hash MySQL functions (to be implemented) */
/* hash all database names */
2001-10-08 03:58:07 +02:00
if ( mysql_query ( & mysql , " show databases " ) = = 0 )
{
2000-07-31 21:29:14 +02:00
if ( ! ( databases = mysql_store_result ( & mysql ) ) )
put_info ( mysql_error ( & mysql ) , INFO_INFO ) ;
else
{
while ( ( database_row = mysql_fetch_row ( databases ) ) )
2001-10-08 03:58:07 +02:00
{
char * str = strdup_root ( & hash_mem_root , ( char * ) database_row [ 0 ] ) ;
if ( str )
add_word ( & ht , ( char * ) str ) ;
}
mysql_free_result ( databases ) ;
2000-07-31 21:29:14 +02:00
}
}
/* hash all table names */
if ( mysql_query ( & mysql , " show tables " ) = = 0 )
{
if ( ! ( tables = mysql_store_result ( & mysql ) ) )
put_info ( mysql_error ( & mysql ) , INFO_INFO ) ;
else
{
if ( mysql_num_rows ( tables ) > 0 & & ! opt_silent & & write_info )
{
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " \
2000-07-31 21:29:14 +02:00
Reading table information for completion of table and column names \ n \
You can turn off this feature to get a quicker startup with - A \ n \ n " );
}
while ( ( table_row = mysql_fetch_row ( tables ) ) )
{
2001-10-08 03:58:07 +02:00
char * str = strdup_root ( & hash_mem_root , ( char * ) table_row [ 0 ] ) ;
if ( str & &
! completion_hash_exists ( & ht , ( char * ) str , ( uint ) strlen ( str ) ) )
add_word ( & ht , str ) ;
2000-07-31 21:29:14 +02:00
}
}
}
/* hash all field names, both with the table prefix and without it */
2001-01-12 12:52:32 +01:00
if ( ! tables ) /* no tables */
{
2000-07-31 21:29:14 +02:00
DBUG_VOID_RETURN ;
}
mysql_data_seek ( tables , 0 ) ;
2001-10-08 03:58:07 +02:00
if ( ! ( field_names = ( char * * * ) alloc_root ( & hash_mem_root , sizeof ( char * * ) *
( uint ) ( mysql_num_rows ( tables ) + 1 ) ) ) )
{
mysql_free_result ( tables ) ;
2000-07-31 21:29:14 +02:00
DBUG_VOID_RETURN ;
2001-10-08 03:58:07 +02:00
}
2000-07-31 21:29:14 +02:00
i = 0 ;
while ( ( table_row = mysql_fetch_row ( tables ) ) )
{
if ( ( fields = mysql_list_fields ( & mysql , ( const char * ) table_row [ 0 ] , NullS ) ) )
{
num_fields = mysql_num_fields ( fields ) ;
2001-10-08 03:58:07 +02:00
if ( ! ( field_names [ i ] = ( char * * ) alloc_root ( & hash_mem_root ,
sizeof ( char * ) *
( num_fields * 2 + 1 ) ) ) )
break ;
2000-07-31 21:29:14 +02:00
field_names [ i ] [ num_fields * 2 ] = ' \0 ' ;
j = 0 ;
while ( ( sql_field = mysql_fetch_field ( fields ) ) )
{
sprintf ( buf , " %s.%s " , table_row [ 0 ] , sql_field - > name ) ;
2001-10-08 03:58:07 +02:00
field_names [ i ] [ j ] = strdup_root ( & hash_mem_root , buf ) ;
2000-07-31 21:29:14 +02:00
add_word ( & ht , field_names [ i ] [ j ] ) ;
2001-10-08 03:58:07 +02:00
field_names [ i ] [ num_fields + j ] = strdup_root ( & hash_mem_root ,
sql_field - > name ) ;
2000-07-31 21:29:14 +02:00
if ( ! completion_hash_exists ( & ht , field_names [ i ] [ num_fields + j ] ,
2000-08-21 23:18:32 +02:00
( uint ) strlen ( field_names [ i ] [ num_fields + j ] ) ) )
2000-07-31 21:29:14 +02:00
add_word ( & ht , field_names [ i ] [ num_fields + j ] ) ;
j + + ;
}
2001-10-08 03:58:07 +02:00
mysql_free_result ( fields ) ;
2000-07-31 21:29:14 +02:00
}
else
2001-01-12 12:52:32 +01:00
{
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout ,
" Didn't find any fields in table '%s' \n " , table_row [ 0 ] ) ;
2001-01-12 12:52:32 +01:00
field_names [ i ] = 0 ;
}
2000-07-31 21:29:14 +02:00
i + + ;
}
2001-10-08 03:58:07 +02:00
mysql_free_result ( tables ) ;
2001-01-12 12:52:32 +01:00
field_names [ i ] = 0 ; // End pointer
2000-07-31 21:29:14 +02:00
DBUG_VOID_RETURN ;
}
/* for gnu readline */
# ifndef HAVE_INDEX
extern " C " {
2002-06-30 17:57:21 +02:00
extern char * index ( const char * , int c ) , * rindex ( const char * , int ) ;
2000-07-31 21:29:14 +02:00
2002-06-30 17:57:21 +02:00
char * index ( const char * s , int c )
2000-07-31 21:29:14 +02:00
{
for ( ; ; )
{
if ( * s = = ( char ) c ) return ( char * ) s ;
if ( ! * s + + ) return NullS ;
}
}
2002-06-30 17:57:21 +02:00
char * rindex ( const char * s , int c )
2000-07-31 21:29:14 +02:00
{
reg3 char * t ;
t = NullS ;
do if ( * s = = ( char ) c ) t = ( char * ) s ; while ( * s + + ) ;
return ( char * ) t ;
}
}
# endif
# endif /* HAVE_READLINE */
2002-06-11 10:20:31 +02:00
2000-07-31 21:29:14 +02:00
static int reconnect ( void )
{
if ( ! status . batch )
{
put_info ( " No connection. Trying to reconnect... " , INFO_INFO ) ;
( void ) com_connect ( ( String * ) 0 , 0 ) ;
2002-06-11 10:20:31 +02:00
if ( rehash )
com_rehash ( NULL , NULL ) ;
2000-07-31 21:29:14 +02:00
}
if ( ! connected )
return put_info ( " Can't connect to the server \n " , INFO_ERROR ) ;
return 0 ;
}
/***************************************************************************
The different commands
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-10-28 14:44:19 +01:00
int mysql_real_query_for_lazy ( const char * buf , int length )
{
for ( uint retry = 0 ; ; retry + + )
{
if ( ! mysql_real_query ( & mysql , buf , length ) )
return 0 ;
uint error = put_info ( mysql_error ( & mysql ) , INFO_ERROR , mysql_errno ( & mysql ) ) ;
if ( mysql_errno ( & mysql ) ! = CR_SERVER_GONE_ERROR | | retry > 1
| | status . batch )
return error ;
if ( reconnect ( ) )
return error ;
}
}
int mysql_store_result_for_lazy ( MYSQL_RES * * result )
{
if ( ( * result = mysql_store_result ( & mysql ) ) )
return 0 ;
if ( mysql_error ( & mysql ) [ 0 ] )
return put_info ( mysql_error ( & mysql ) , INFO_ERROR , mysql_errno ( & mysql ) ) ;
return 0 ;
}
static int com_server_help ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) , char * help_arg )
{
MYSQL_ROW cur ;
const char * server_cmd = buffer - > ptr ( ) ;
char cmd_buf [ 100 ] ;
if ( help_arg [ 0 ] ! = ' \' ' )
{
( void * ) sprintf ( cmd_buf , " help \' %s \' ; " , help_arg ) ;
server_cmd = cmd_buf ;
}
char buff [ 16 ] , time_buf [ 32 ] ;
MYSQL_RES * result ;
ulong timer ;
uint error = 0 ;
if ( ! status . batch )
{
old_buffer = * buffer ;
old_buffer . copy ( ) ;
}
if ( ! connected & & reconnect ( ) )
return 1 ;
timer = start_timer ( ) ;
error = mysql_real_query_for_lazy ( server_cmd , strlen ( server_cmd ) ) ;
if ( error )
return error ;
error = mysql_store_result_for_lazy ( & result ) ;
if ( error )
return error ;
if ( result )
{
int num_rows = mysql_num_rows ( result ) ;
if ( num_rows = = 1 )
{
if ( ! ( cur = mysql_fetch_row ( result ) ) )
return - 1 ;
init_pager ( ) ;
if ( cur [ 1 ] [ 0 ] = = ' Y ' )
{
tee_fprintf ( PAGER , " \n Help topic \' %s \' \n " , cur [ 0 ] ) ;
tee_fprintf ( PAGER , " %s \n " , cur [ 2 ] ) ;
tee_fprintf ( PAGER , " For help on specific function please type 'help <function>' where function is one of next : \n %s \n " , cur [ 3 ] ) ;
}
else
{
tee_fprintf ( PAGER , " \n Name : \' %s \' \n \n " , cur [ 0 ] ) ;
tee_fprintf ( PAGER , " Description : \n %s \n \n " , cur [ 2 ] ) ;
tee_fprintf ( PAGER , " Examples : \n %s \n " , cur [ 3 ] ) ;
}
end_pager ( ) ;
}
else if ( num_rows > 1 )
{
put_info ( " \n Many help items for your request exist " , INFO_INFO ) ;
put_info ( " For more specific request please type 'help <item>' where item is one of next : " , INFO_INFO ) ;
init_pager ( ) ;
char last_char = ' _ ' ;
while ( ( cur = mysql_fetch_row ( result ) ) ) {
if ( cur [ 1 ] [ 0 ] ! = last_char ) {
put_info ( " ------------------------------------------- " , INFO_INFO ) ;
put_info ( cur [ 1 ] [ 0 ] = = ' Y ' ?
" categories: " : " functions: " , INFO_INFO ) ;
put_info ( " ------------------------------------------- " , INFO_INFO ) ;
}
last_char = cur [ 1 ] [ 0 ] ;
tee_fprintf ( PAGER , " %s \n " , cur [ 0 ] ) ;
}
tee_fprintf ( PAGER , " \n " ) ;
end_pager ( ) ;
}
else
{
put_info ( " \n Nothing found \n " , INFO_INFO ) ;
}
}
mysql_free_result ( result ) ;
return error ;
}
2000-07-31 21:29:14 +02:00
static int
com_help ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
{
reg1 int i ;
2002-10-28 14:44:19 +01:00
char * help_arg = strchr ( line , ' ' ) ;
2000-07-31 21:29:14 +02:00
2002-10-28 14:44:19 +01:00
if ( help_arg )
2000-07-31 21:29:14 +02:00
{
2002-10-28 14:44:19 +01:00
return com_server_help ( buffer , line , help_arg + 1 ) ;
2000-07-31 21:29:14 +02:00
}
2002-10-28 14:44:19 +01:00
else
{
put_info ( " \n For the complete MySQL Manual online visit: \n http://www.mysql.com/documentation \n " , INFO_INFO ) ;
put_info ( " For info on technical support from MySQL developers visit: \n http://www.mysql.com/support \n " , INFO_INFO ) ;
put_info ( " For info on MySQL books, utilities, consultants, etc. visit: \n http://www.mysql.com/portal \n " , INFO_INFO ) ;
put_info ( " List of all MySQL commands: " , INFO_INFO ) ;
if ( ! named_cmds )
put_info ( " Note that all text commands must be first on line and end with ';' " , INFO_INFO ) ;
for ( i = 0 ; commands [ i ] . name ; i + + )
{
if ( commands [ i ] . func )
tee_fprintf ( stdout , " %s \t ( \\ %c) \t %s \n " , commands [ i ] . name ,
commands [ i ] . cmd_char , commands [ i ] . doc ) ;
}
if ( connected )
tee_fprintf ( stdout ,
2000-11-17 13:33:29 +01:00
" \n Connection id: %ld (Can be used with mysqladmin kill) \n \n " ,
mysql_thread_id ( & mysql ) ) ;
2002-10-28 14:44:19 +01:00
else
tee_fprintf ( stdout , " Not connected! Reconnect with 'connect'! \n \n " ) ;
}
2000-07-31 21:29:14 +02:00
return 0 ;
}
/* ARGSUSED */
static int
com_clear ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
buffer - > length ( 0 ) ;
return 0 ;
}
/*
2002-06-11 10:20:31 +02:00
Execute command
Returns : 0 if ok
- 1 if not fatal error
1 if fatal error
2000-07-31 21:29:14 +02:00
*/
static int
com_go ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
2002-10-02 12:33:08 +02:00
char buff [ 200 ] , time_buff [ 32 ] , * pos ;
2000-07-31 21:29:14 +02:00
MYSQL_RES * result ;
2002-10-02 12:33:08 +02:00
ulong timer , warnings ;
2000-07-31 21:29:14 +02:00
uint error = 0 ;
if ( ! status . batch )
{
old_buffer = * buffer ; // Save for edit command
old_buffer . copy ( ) ;
}
2002-06-11 10:20:31 +02:00
/* Remove garbage for nicer messages */
2000-07-31 21:29:14 +02:00
LINT_INIT ( buff [ 0 ] ) ;
remove_cntrl ( * buffer ) ;
if ( buffer - > is_empty ( ) )
{
if ( status . batch ) // Ignore empty quries
return 0 ;
return put_info ( " No query specified \n " , INFO_ERROR ) ;
}
if ( ! connected & & reconnect ( ) )
{
buffer - > length ( 0 ) ; // Remove query on error
return status . batch ? 1 : - 1 ; // Fatal error
}
if ( verbose )
( void ) com_print ( buffer , 0 ) ;
if ( skip_updates & &
2002-10-09 13:33:35 +02:00
( buffer - > length ( ) < 4 | | my_strnncoll ( system_charset_info ,
( const uchar * ) buffer - > ptr ( ) , 4 ,
( const uchar * ) " SET " , 4 ) ) )
2000-07-31 21:29:14 +02:00
{
( void ) put_info ( " Ignoring query to other database " , INFO_INFO ) ;
return 0 ;
}
timer = start_timer ( ) ;
2002-10-28 14:44:19 +01:00
error = mysql_real_query_for_lazy ( buffer - > ptr ( ) , buffer - > length ( ) ) ;
if ( error )
2000-07-31 21:29:14 +02:00
{
2002-10-28 14:44:19 +01:00
buffer - > length ( 0 ) ; // Remove query on error
return error ;
2000-07-31 21:29:14 +02:00
}
2002-10-28 14:44:19 +01:00
2000-07-31 21:29:14 +02:00
error = 0 ;
buffer - > length ( 0 ) ;
if ( quick )
{
if ( ! ( result = mysql_use_result ( & mysql ) ) & & mysql_field_count ( & mysql ) )
{
return put_info ( mysql_error ( & mysql ) , INFO_ERROR , mysql_errno ( & mysql ) ) ;
}
}
else
{
2002-10-28 14:44:19 +01:00
error = mysql_store_result_for_lazy ( & result ) ;
if ( error )
return error ;
2000-07-31 21:29:14 +02:00
}
if ( verbose > = 3 | | ! opt_silent )
mysql_end_timer ( timer , time_buff ) ;
else
time_buff [ 0 ] = 0 ;
if ( result )
{
if ( ! mysql_num_rows ( result ) & & ! quick )
{
2002-10-02 12:33:08 +02:00
strmov ( buff , " Empty set " ) ;
2000-07-31 21:29:14 +02:00
}
else
{
2000-11-17 13:33:29 +01:00
init_pager ( ) ;
2000-07-31 21:29:14 +02:00
if ( opt_html )
print_table_data_html ( result ) ;
2001-04-11 13:04:03 +02:00
else if ( opt_xml )
print_table_data_xml ( result ) ;
2000-07-31 21:29:14 +02:00
else if ( vertical )
print_table_data_vertically ( result ) ;
else if ( opt_silent & & verbose < = 2 & & ! output_tables )
print_tab_data ( result ) ;
else
print_table_data ( result ) ;
2002-10-02 12:33:08 +02:00
sprintf ( buff , " %ld %s in set " ,
2000-07-31 21:29:14 +02:00
( long ) mysql_num_rows ( result ) ,
2002-10-02 12:33:08 +02:00
( long ) mysql_num_rows ( result ) = = 1 ? " row " : " rows " ) ;
2000-11-17 13:33:29 +01:00
end_pager ( ) ;
2000-07-31 21:29:14 +02:00
}
}
else if ( mysql_affected_rows ( & mysql ) = = ~ ( ulonglong ) 0 )
2002-10-02 12:33:08 +02:00
strmov ( buff , " Query OK " ) ;
2000-07-31 21:29:14 +02:00
else
2002-10-02 12:33:08 +02:00
sprintf ( buff , " Query OK, %ld %s affected " ,
2000-07-31 21:29:14 +02:00
( long ) mysql_affected_rows ( & mysql ) ,
2002-10-02 12:33:08 +02:00
( long ) mysql_affected_rows ( & mysql ) = = 1 ? " row " : " rows " ) ;
pos = strend ( buff ) ;
if ( ( warnings = mysql_warning_count ( & mysql ) ) )
{
* pos + + = ' , ' ;
* pos + + = ' ' ;
pos = int2str ( warnings , pos , 10 ) ;
pos = strmov ( pos , " warning " ) ;
if ( warnings ! = 1 )
* pos + + = ' s ' ;
}
strmov ( pos , time_buff ) ;
2000-07-31 21:29:14 +02:00
put_info ( buff , INFO_RESULT ) ;
if ( mysql_info ( & mysql ) )
put_info ( mysql_info ( & mysql ) , INFO_RESULT ) ;
put_info ( " " , INFO_RESULT ) ; // Empty row
if ( result & & ! mysql_eof ( result ) ) /* Something wrong when using quick */
error = put_info ( mysql_error ( & mysql ) , INFO_ERROR , mysql_errno ( & mysql ) ) ;
else if ( unbuffered )
fflush ( stdout ) ;
mysql_free_result ( result ) ;
return error ; /* New command follows */
}
2000-11-17 13:33:29 +01:00
static void init_pager ( )
{
2002-07-23 17:31:22 +02:00
# if !defined( __WIN__) && !defined( OS2) && (!defined(HAVE_mit_thread) || !defined(THREAD))
2000-11-17 13:33:29 +01:00
if ( ! opt_nopager )
{
if ( ! ( PAGER = popen ( pager , " w " ) ) )
{
tee_fprintf ( stdout , " popen() failed! defaulting PAGER to stdout! \n " ) ;
PAGER = stdout ;
}
}
else
# endif
PAGER = stdout ;
}
static void end_pager ( )
{
2002-07-16 16:19:10 +02:00
# if !defined( __WIN__) && !defined( OS2) && !(defined(HAVE_mit_thread) && defined(THREAD))
2000-11-17 13:33:29 +01:00
if ( ! opt_nopager )
pclose ( PAGER ) ;
# endif
}
2002-06-12 16:35:04 +02:00
static int init_tee ( char * newfile )
2000-11-17 13:33:29 +01:00
{
2002-06-12 16:35:04 +02:00
FILE * new_outfile ;
if ( ! ( new_outfile = my_fopen ( newfile , O_APPEND | O_WRONLY , MYF ( MY_WME ) ) ) )
return 0 ;
2002-05-31 11:34:47 +02:00
if ( opt_outfile )
2002-06-12 16:35:04 +02:00
end_tee ( ) ;
OUTFILE = new_outfile ;
strmake ( outfile , newfile , FN_REFLEN - 1 ) ;
2002-05-31 11:34:47 +02:00
tee_fprintf ( stdout , " Logging to file '%s' \n " , outfile ) ;
2002-06-12 16:35:04 +02:00
return 1 ;
2000-11-17 13:33:29 +01:00
}
2002-06-12 16:35:04 +02:00
2000-11-17 13:33:29 +01:00
static void end_tee ( )
{
my_fclose ( OUTFILE , MYF ( 0 ) ) ;
2002-05-31 11:34:47 +02:00
opt_outfile = 0 ;
2000-11-17 13:33:29 +01:00
return ;
}
2000-07-31 21:29:14 +02:00
static int
com_ego ( String * buffer , char * line )
{
int result ;
bool oldvertical = vertical ;
vertical = 1 ;
result = com_go ( buffer , line ) ;
vertical = oldvertical ;
return result ;
}
2001-03-11 20:20:15 +01:00
static void
print_field_types ( MYSQL_RES * result )
{
MYSQL_FIELD * field ;
while ( ( field = mysql_fetch_field ( result ) ) )
{
tee_fprintf ( PAGER , " %s '%s' %d %d %d %d %d \n " ,
field - > name ,
field - > table ? " " : field - > table ,
( int ) field - > type ,
field - > length , field - > max_length ,
field - > flags , field - > decimals ) ;
}
tee_puts ( " " , PAGER ) ;
}
2000-07-31 21:29:14 +02:00
static void
print_table_data ( MYSQL_RES * result )
{
String separator ( 256 ) ;
MYSQL_ROW cur ;
MYSQL_FIELD * field ;
bool * num_flag ;
num_flag = ( bool * ) my_alloca ( sizeof ( bool ) * mysql_num_fields ( result ) ) ;
2001-03-11 20:20:15 +01:00
if ( info_flag )
{
print_field_types ( result ) ;
mysql_field_seek ( result , 0 ) ;
}
2002-11-10 11:05:17 +01:00
separator . copy ( " + " , 1 , system_charset_info ) ;
2000-07-31 21:29:14 +02:00
while ( ( field = mysql_fetch_field ( result ) ) )
{
2002-04-02 19:29:53 +02:00
uint length = column_names ? ( uint ) strlen ( field - > name ) : 0 ;
2000-07-31 21:29:14 +02:00
if ( quick )
length = max ( length , field - > length ) ;
else
length = max ( length , field - > max_length ) ;
if ( length < 4 & & ! IS_NOT_NULL ( field - > flags ) )
length = 4 ; // Room for "NULL"
field - > max_length = length + 1 ;
separator . fill ( separator . length ( ) + length + 2 , ' - ' ) ;
separator . append ( ' + ' ) ;
}
2000-11-17 13:33:29 +01:00
tee_puts ( separator . c_ptr ( ) , PAGER ) ;
2002-04-02 19:29:53 +02:00
if ( column_names )
2000-07-31 21:29:14 +02:00
{
mysql_field_seek ( result , 0 ) ;
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " | " , PAGER ) ;
2000-07-31 21:29:14 +02:00
for ( uint off = 0 ; ( field = mysql_fetch_field ( result ) ) ; off + + )
{
2001-02-02 02:47:06 +01:00
tee_fprintf ( PAGER , " %-*s| " , min ( field - > max_length , MAX_COLUMN_LENGTH ) ,
field - > name ) ;
2000-07-31 21:29:14 +02:00
num_flag [ off ] = IS_NUM ( field - > type ) ;
}
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " \n " , PAGER ) ;
tee_puts ( separator . c_ptr ( ) , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
2002-05-31 14:43:21 +02:00
while ( ( cur = mysql_fetch_row ( result ) ) )
2000-07-31 21:29:14 +02:00
{
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " | " , PAGER ) ;
2002-05-31 14:43:21 +02:00
mysql_field_seek ( result , 0 ) ;
for ( uint off = 0 ; off < mysql_num_fields ( result ) ; off + + )
2000-07-31 21:29:14 +02:00
{
2002-05-31 14:43:21 +02:00
const char * str = cur [ off ] ? cur [ off ] : " NULL " ;
field = mysql_fetch_field ( result ) ;
uint length = field - > max_length ;
2001-02-02 02:47:06 +01:00
if ( length > MAX_COLUMN_LENGTH )
{
2002-05-31 14:43:21 +02:00
tee_fputs ( str , PAGER ) ;
tee_fputs ( " | " , PAGER ) ;
2001-02-02 02:47:06 +01:00
}
else
2000-11-17 13:33:29 +01:00
tee_fprintf ( PAGER , num_flag [ off ] ? " %*s | " : " %-*s| " ,
2001-02-02 02:47:06 +01:00
length , str ) ;
2000-07-31 21:29:14 +02:00
}
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " \n " , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
2000-11-17 13:33:29 +01:00
tee_puts ( separator . c_ptr ( ) , PAGER ) ;
2000-07-31 21:29:14 +02:00
my_afree ( ( gptr ) num_flag ) ;
}
static void
print_table_data_html ( MYSQL_RES * result )
{
MYSQL_ROW cur ;
MYSQL_FIELD * field ;
mysql_field_seek ( result , 0 ) ;
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " <TABLE BORDER=1><TR> " , PAGER ) ;
2002-04-02 19:29:53 +02:00
if ( column_names )
2000-07-31 21:29:14 +02:00
{
while ( ( field = mysql_fetch_field ( result ) ) )
{
2000-11-17 13:33:29 +01:00
tee_fprintf ( PAGER , " <TH>%s</TH> " , ( field - > name ?
( field - > name [ 0 ] ? field - > name :
" " ) : " NULL " ) ) ;
2000-07-31 21:29:14 +02:00
}
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " </TR> " , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
while ( ( cur = mysql_fetch_row ( result ) ) )
{
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " <TR> " , PAGER ) ;
2000-07-31 21:29:14 +02:00
for ( uint i = 0 ; i < mysql_num_fields ( result ) ; i + + )
{
ulong * lengths = mysql_fetch_lengths ( result ) ;
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " <TD> " , PAGER ) ;
2000-07-31 21:29:14 +02:00
safe_put_field ( cur [ i ] , lengths [ i ] ) ;
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " </TD> " , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " </TR> " , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " </TABLE> " , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
2001-04-11 13:04:03 +02:00
static void
print_table_data_xml ( MYSQL_RES * result )
{
MYSQL_ROW cur ;
MYSQL_FIELD * fields ;
mysql_field_seek ( result , 0 ) ;
2001-12-14 16:43:18 +01:00
tee_fputs ( " <?xml version= \" 1.0 \" ?> \n \n <resultset statement= \" " , PAGER ) ;
2002-04-03 12:36:01 +02:00
xmlencode_print ( glob_buffer . ptr ( ) , strlen ( glob_buffer . ptr ( ) ) ) ;
2001-12-14 16:43:18 +01:00
tee_fputs ( " \" > " , PAGER ) ;
2001-04-11 13:04:03 +02:00
fields = mysql_fetch_fields ( result ) ;
while ( ( cur = mysql_fetch_row ( result ) ) )
{
( void ) tee_fputs ( " \n <row> \n " , PAGER ) ;
for ( uint i = 0 ; i < mysql_num_fields ( result ) ; i + + )
{
ulong * lengths = mysql_fetch_lengths ( result ) ;
tee_fprintf ( PAGER , " \t <%s> " , ( fields [ i ] . name ?
( fields [ i ] . name [ 0 ] ? fields [ i ] . name :
" " ) : " NULL " ) ) ;
2001-12-14 16:43:18 +01:00
xmlencode_print ( cur [ i ] , lengths [ i ] ) ;
2001-04-11 13:04:03 +02:00
tee_fprintf ( PAGER , " </%s> \n " , ( fields [ i ] . name ?
( fields [ i ] . name [ 0 ] ? fields [ i ] . name :
" " ) : " NULL " ) ) ;
}
( void ) tee_fputs ( " </row> \n " , PAGER ) ;
}
( void ) tee_fputs ( " </resultset> \n " , PAGER ) ;
}
2000-07-31 21:29:14 +02:00
static void
print_table_data_vertically ( MYSQL_RES * result )
{
MYSQL_ROW cur ;
uint max_length = 0 ;
MYSQL_FIELD * field ;
while ( ( field = mysql_fetch_field ( result ) ) )
{
2000-08-21 23:18:32 +02:00
uint length = ( uint ) strlen ( field - > name ) ;
2000-07-31 21:29:14 +02:00
if ( length > max_length )
max_length = length ;
field - > max_length = length ;
}
mysql_field_seek ( result , 0 ) ;
for ( uint row_count = 1 ; ( cur = mysql_fetch_row ( result ) ) ; row_count + + )
{
mysql_field_seek ( result , 0 ) ;
2000-11-17 13:33:29 +01:00
tee_fprintf ( PAGER ,
" *************************** %d. row *************************** \n " , row_count ) ;
2000-07-31 21:29:14 +02:00
for ( uint off = 0 ; off < mysql_num_fields ( result ) ; off + + )
{
field = mysql_fetch_field ( result ) ;
2000-11-17 13:33:29 +01:00
tee_fprintf ( PAGER , " %*s: " , ( int ) max_length , field - > name ) ;
tee_fprintf ( PAGER , " %s \n " , cur [ off ] ? ( char * ) cur [ off ] : " NULL " ) ;
2000-07-31 21:29:14 +02:00
}
}
}
2001-12-14 16:43:18 +01:00
2001-04-25 00:11:29 +02:00
static const char
2001-12-14 16:43:18 +01:00
* array_value ( const char * * array , char key )
{
2001-04-11 13:04:03 +02:00
int x ;
2001-12-14 16:43:18 +01:00
for ( x = 0 ; array [ x ] ; x + = 2 )
if ( * array [ x ] = = key )
return array [ x + 1 ] ;
2001-04-11 13:04:03 +02:00
return 0 ;
}
2001-12-14 16:43:18 +01:00
2001-04-25 00:11:29 +02:00
static void
2001-12-14 16:43:18 +01:00
xmlencode_print ( const char * src , uint length )
2001-04-25 00:11:29 +02:00
{
2001-12-14 16:43:18 +01:00
if ( ! src )
tee_fputs ( " NULL " , PAGER ) ;
else
2001-04-25 00:11:29 +02:00
{
2001-12-14 16:43:18 +01:00
for ( const char * p = src ; * p & & length ; * p + + , length - - )
{
const char * t ;
if ( ( t = array_value ( xmlmeta , * p ) ) )
tee_fputs ( t , PAGER ) ;
else
tee_putc ( * p , PAGER ) ;
}
}
2001-04-11 13:04:03 +02:00
}
2001-12-06 13:10:51 +01:00
2000-07-31 21:29:14 +02:00
static void
safe_put_field ( const char * pos , ulong length )
{
if ( ! pos )
2000-11-17 13:33:29 +01:00
tee_fputs ( " NULL " , PAGER ) ;
2000-07-31 21:29:14 +02:00
else
{
if ( opt_raw_data )
2000-11-17 13:33:29 +01:00
tee_fputs ( pos , PAGER ) ;
2000-07-31 21:29:14 +02:00
else for ( const char * end = pos + length ; pos ! = end ; pos + + )
{
# ifdef USE_MB
int l ;
2002-03-14 17:52:48 +01:00
if ( use_mb ( system_charset_info ) & &
2002-08-30 11:40:40 +02:00
( l = my_ismbchar ( system_charset_info , pos , end ) ) )
{
2000-07-31 21:29:14 +02:00
while ( l - - )
2000-11-18 16:34:15 +01:00
tee_putc ( * pos + + , PAGER ) ;
2000-07-31 21:29:14 +02:00
pos - - ;
continue ;
}
# endif
if ( ! * pos )
2000-11-17 13:33:29 +01:00
tee_fputs ( " \\ 0 " , PAGER ) ; // This makes everything hard
2000-07-31 21:29:14 +02:00
else if ( * pos = = ' \t ' )
2000-11-17 13:33:29 +01:00
tee_fputs ( " \\ t " , PAGER ) ; // This would destroy tab format
2000-07-31 21:29:14 +02:00
else if ( * pos = = ' \n ' )
2000-11-17 13:33:29 +01:00
tee_fputs ( " \\ n " , PAGER ) ; // This too
2000-07-31 21:29:14 +02:00
else if ( * pos = = ' \\ ' )
2000-11-17 13:33:29 +01:00
tee_fputs ( " \\ \\ " , PAGER ) ;
2001-04-11 13:04:03 +02:00
else
2000-11-18 16:34:15 +01:00
tee_putc ( * pos , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
}
}
static void
print_tab_data ( MYSQL_RES * result )
{
MYSQL_ROW cur ;
MYSQL_FIELD * field ;
ulong * lengths ;
2002-04-02 19:29:53 +02:00
if ( opt_silent < 2 & & column_names )
2000-07-31 21:29:14 +02:00
{
int first = 0 ;
while ( ( field = mysql_fetch_field ( result ) ) )
{
if ( first + + )
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " \t " , PAGER ) ;
( void ) tee_fputs ( field - > name , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " \n " , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
while ( ( cur = mysql_fetch_row ( result ) ) )
{
lengths = mysql_fetch_lengths ( result ) ;
safe_put_field ( cur [ 0 ] , lengths [ 0 ] ) ;
for ( uint off = 1 ; off < mysql_num_fields ( result ) ; off + + )
{
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " \t " , PAGER ) ;
2002-05-31 11:34:47 +02:00
safe_put_field ( cur [ off ] , lengths [ off ] ) ;
2000-07-31 21:29:14 +02:00
}
2000-11-17 13:33:29 +01:00
( void ) tee_fputs ( " \n " , PAGER ) ;
2000-07-31 21:29:14 +02:00
}
}
2000-11-17 13:33:29 +01:00
static int
com_tee ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
char file_name [ FN_REFLEN ] , * end , * param ;
if ( status . batch )
return 0 ;
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * line ) )
2000-11-17 13:33:29 +01:00
line + + ;
if ( ! ( param = strchr ( line , ' ' ) ) ) // if outfile wasn't given, use the default
{
if ( ! strlen ( outfile ) )
{
2002-05-31 11:34:47 +02:00
printf ( " No previous outfile available, you must give a filename! \n " ) ;
2000-11-17 13:33:29 +01:00
return 0 ;
}
2002-06-12 16:35:04 +02:00
else if ( opt_outfile )
{
tee_fprintf ( stdout , " Currently logging to file '%s' \n " , outfile ) ;
return 0 ;
}
else
param = outfile ; //resume using the old outfile
2000-11-17 13:33:29 +01:00
}
2002-06-12 16:35:04 +02:00
/* eliminate the spaces before the parameters */
2002-08-30 11:40:40 +02:00
while ( my_isspace ( system_charset_info , * param ) )
2002-06-12 16:35:04 +02:00
param + + ;
end = strmake ( file_name , param , sizeof ( file_name ) - 1 ) ;
/* remove end space from command line */
2002-08-30 11:40:40 +02:00
while ( end > file_name & & ( my_isspace ( system_charset_info , end [ - 1 ] ) | |
my_iscntrl ( system_charset_info , end [ - 1 ] ) ) )
2002-06-12 16:35:04 +02:00
end - - ;
end [ 0 ] = 0 ;
2002-09-03 14:44:25 +02:00
if ( end = = file_name )
2000-11-17 13:33:29 +01:00
{
printf ( " No outfile specified! \n " ) ;
return 0 ;
}
2002-06-12 16:35:04 +02:00
opt_outfile = init_tee ( file_name ) ;
if ( opt_outfile )
tee_fprintf ( stdout , " Logging to file '%s' \n " , outfile ) ;
else
tee_fprintf ( stdout , " Error logging to file '%s' \n " , file_name ) ;
2000-11-17 13:33:29 +01:00
return 0 ;
}
2002-06-12 16:35:04 +02:00
2000-11-17 13:33:29 +01:00
static int
com_notee ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
{
if ( opt_outfile )
end_tee ( ) ;
tee_fprintf ( stdout , " Outfile disabled. \n " ) ;
return 0 ;
}
2000-11-22 02:45:02 +01:00
/*
2002-06-11 10:20:31 +02:00
Sorry , this command is not available in Windows .
2000-11-22 02:45:02 +01:00
*/
# ifndef __WIN__
2000-11-17 13:33:29 +01:00
static int
com_pager ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
char pager_name [ FN_REFLEN ] , * end , * param ;
if ( status . batch )
return 0 ;
/* Skip space from file name */
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * line ) )
2000-11-17 13:33:29 +01:00
line + + ;
if ( ! ( param = strchr ( line , ' ' ) ) ) // if pager was not given, use the default
{
if ( ! strlen ( default_pager ) )
{
2000-11-20 20:22:02 +01:00
tee_fprintf ( stdout , " Default pager wasn't set, using stdout. \n " ) ;
2000-11-17 13:33:29 +01:00
opt_nopager = 1 ;
strmov ( pager , " stdout " ) ;
PAGER = stdout ;
return 0 ;
}
strmov ( pager , default_pager ) ;
}
else
{
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * param ) )
2000-11-17 13:33:29 +01:00
param + + ;
end = strmake ( pager_name , param , sizeof ( pager_name ) - 1 ) ;
2002-03-12 18:37:58 +01:00
while ( end > pager_name & & ( my_isspace ( system_charset_info , end [ - 1 ] ) | |
my_iscntrl ( system_charset_info , end [ - 1 ] ) ) )
2000-11-17 13:33:29 +01:00
end - - ;
end [ 0 ] = 0 ;
strmov ( pager , pager_name ) ;
2001-04-11 05:17:20 +02:00
strmov ( default_pager , pager_name ) ;
2000-11-17 13:33:29 +01:00
}
opt_nopager = 0 ;
tee_fprintf ( stdout , " PAGER set to %s \n " , pager ) ;
return 0 ;
}
2000-11-22 02:45:02 +01:00
2000-11-17 13:33:29 +01:00
static int
com_nopager ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
{
strmov ( pager , " stdout " ) ;
opt_nopager = 1 ;
tee_fprintf ( stdout , " PAGER set to stdout \n " ) ;
return 0 ;
}
2000-11-22 02:45:02 +01:00
# endif
2000-11-17 13:33:29 +01:00
2000-07-31 21:29:14 +02:00
2000-11-22 02:45:02 +01:00
/*
2002-06-11 10:20:31 +02:00
Sorry , you can ' t send the result to an editor in Win32
2000-11-22 02:45:02 +01:00
*/
# ifndef __WIN__
2000-07-31 21:29:14 +02:00
static int
com_edit ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
2000-10-03 13:18:03 +02:00
char filename [ FN_REFLEN ] , buff [ 160 ] ;
2000-07-31 21:29:14 +02:00
int fd , tmp ;
const char * editor ;
2000-10-03 13:18:03 +02:00
if ( ( fd = create_temp_file ( filename , NullS , " sql " , O_CREAT | O_WRONLY ,
MYF ( MY_WME ) ) ) < 0 )
2000-07-31 21:29:14 +02:00
goto err ;
if ( buffer - > is_empty ( ) & & ! old_buffer . is_empty ( ) )
( void ) my_write ( fd , ( byte * ) old_buffer . ptr ( ) , old_buffer . length ( ) ,
MYF ( MY_WME ) ) ;
else
( void ) my_write ( fd , ( byte * ) buffer - > ptr ( ) , buffer - > length ( ) , MYF ( MY_WME ) ) ;
( void ) my_close ( fd , MYF ( 0 ) ) ;
if ( ! ( editor = ( char * ) getenv ( " EDITOR " ) ) & &
! ( editor = ( char * ) getenv ( " VISUAL " ) ) )
editor = " vi " ;
strxmov ( buff , editor , " " , filename , NullS ) ;
( void ) system ( buff ) ;
MY_STAT stat_arg ;
if ( ! my_stat ( filename , & stat_arg , MYF ( MY_WME ) ) )
goto err ;
if ( ( fd = my_open ( filename , O_RDONLY , MYF ( MY_WME ) ) ) < 0 )
goto err ;
( void ) buffer - > alloc ( ( uint ) stat_arg . st_size ) ;
if ( ( tmp = read ( fd , ( char * ) buffer - > ptr ( ) , buffer - > alloced_length ( ) ) ) > = 0L )
buffer - > length ( ( uint ) tmp ) ;
else
buffer - > length ( 0 ) ;
( void ) my_close ( fd , MYF ( 0 ) ) ;
( void ) my_delete ( filename , MYF ( MY_WME ) ) ;
err :
return 0 ;
}
2000-11-22 02:45:02 +01:00
# endif
2000-07-31 21:29:14 +02:00
/* If arg is given, exit without errors. This happens on command 'quit' */
static int
com_quit ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
{
status . exit_status = 0 ;
return 1 ;
}
static int
com_rehash ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
{
# ifdef HAVE_READLINE
2002-04-16 10:39:03 +02:00
build_completion_hash ( 1 , 0 ) ;
2000-07-31 21:29:14 +02:00
# endif
return 0 ;
}
2001-11-06 22:00:03 +01:00
# ifndef __WIN__
static int
com_shell ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
char * shell_cmd ;
if ( ! ( shell_cmd = strchr ( line , ' ' ) ) )
{
put_info ( " Usage: \\ ! shell-command " , INFO_ERROR ) ;
return - 1 ;
}
2002-06-11 10:20:31 +02:00
/*
The output of the shell command does not
get directed to the pager or the outfile
*/
if ( system ( shell_cmd ) = = - 1 )
2001-11-06 22:00:03 +01:00
{
put_info ( strerror ( errno ) , INFO_ERROR , errno ) ;
return - 1 ;
}
return 0 ;
}
# endif
2000-07-31 21:29:14 +02:00
static int
com_print ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
2000-11-17 13:33:29 +01:00
tee_puts ( " -------------- " , stdout ) ;
( void ) tee_fputs ( buffer - > c_ptr ( ) , stdout ) ;
2000-07-31 21:29:14 +02:00
if ( ! buffer - > length ( ) | | ( * buffer ) [ buffer - > length ( ) - 1 ] ! = ' \n ' )
2000-11-18 16:34:15 +01:00
tee_putc ( ' \n ' , stdout ) ;
2000-11-17 13:33:29 +01:00
tee_puts ( " -------------- \n " , stdout ) ;
2000-07-31 21:29:14 +02:00
return 0 ; /* If empty buffer */
}
/* ARGSUSED */
static int
com_connect ( String * buffer , char * line )
{
char * tmp , buff [ 256 ] ;
2002-04-16 10:39:03 +02:00
bool save_rehash = rehash ;
2000-07-31 21:29:14 +02:00
int error ;
if ( buffer )
{
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * line ) )
2000-07-31 21:29:14 +02:00
line + + ;
strnmov ( buff , line , sizeof ( buff ) - 1 ) ; // Don't destroy history
if ( buff [ 0 ] = = ' \\ ' ) // Short command
buff [ 1 ] = ' ' ;
2000-08-11 17:17:38 +02:00
tmp = ( char * ) strtok ( buff , " \t " ) ; // Skip connect command
2000-07-31 21:29:14 +02:00
if ( tmp & & ( tmp = ( char * ) strtok ( NullS , " \t ; " ) ) )
{
my_free ( current_db , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
current_db = my_strdup ( tmp , MYF ( MY_WME ) ) ;
if ( ( tmp = ( char * ) strtok ( NullS , " \t ; " ) ) )
{
my_free ( current_host , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
current_host = my_strdup ( tmp , MYF ( MY_WME ) ) ;
}
}
else
2002-04-16 10:39:03 +02:00
rehash = 0 ; // Quick re-connect
2000-07-31 21:29:14 +02:00
buffer - > length ( 0 ) ; // command used
}
else
2002-04-16 10:39:03 +02:00
rehash = 0 ;
2000-07-31 21:29:14 +02:00
error = sql_connect ( current_host , current_db , current_user , opt_password , 0 ) ;
2002-04-16 10:39:03 +02:00
rehash = save_rehash ;
2000-07-31 21:29:14 +02:00
if ( connected )
{
sprintf ( buff , " Connection id: %ld " , mysql_thread_id ( & mysql ) ) ;
put_info ( buff , INFO_INFO ) ;
sprintf ( buff , " Current database: %s \n " ,
2000-08-11 17:17:38 +02:00
current_db ? current_db : " *** NONE *** " ) ;
2000-07-31 21:29:14 +02:00
put_info ( buff , INFO_INFO ) ;
}
return error ;
}
static int com_source ( String * buffer , char * line )
{
char source_name [ FN_REFLEN ] , * end , * param ;
LINE_BUFFER * line_buff ;
int error ;
STATUS old_status ;
FILE * sql_file ;
/* Skip space from file name */
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * line ) )
2000-07-31 21:29:14 +02:00
line + + ;
2000-11-17 13:33:29 +01:00
if ( ! ( param = strchr ( line , ' ' ) ) ) // Skip command name
return put_info ( " Usage: \\ . <filename> | source <filename> " ,
INFO_ERROR , 0 ) ;
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * param ) )
2000-07-31 21:29:14 +02:00
param + + ;
end = strmake ( source_name , param , sizeof ( source_name ) - 1 ) ;
2002-03-12 18:37:58 +01:00
while ( end > source_name & & ( my_isspace ( system_charset_info , end [ - 1 ] ) | |
my_iscntrl ( system_charset_info , end [ - 1 ] ) ) )
2000-07-31 21:29:14 +02:00
end - - ;
end [ 0 ] = 0 ;
2000-09-07 03:55:17 +02:00
unpack_filename ( source_name , source_name ) ;
2000-07-31 21:29:14 +02:00
/* open file name */
2000-09-07 03:55:17 +02:00
if ( ! ( sql_file = my_fopen ( source_name , O_RDONLY | O_BINARY , MYF ( 0 ) ) ) )
2000-07-31 21:29:14 +02:00
{
char buff [ FN_REFLEN + 60 ] ;
sprintf ( buff , " Failed to open file '%s', error: %d " , source_name , errno ) ;
return put_info ( buff , INFO_ERROR , 0 ) ;
}
if ( ! ( line_buff = batch_readline_init ( max_allowed_packet + 512 , sql_file ) ) )
{
my_fclose ( sql_file , MYF ( 0 ) ) ;
return put_info ( " Can't initialize batch_readline " , INFO_ERROR , 0 ) ;
}
/* Save old status */
old_status = status ;
bfill ( ( char * ) & status , sizeof ( status ) , ( char ) 0 ) ;
status . batch = old_status . batch ; // Run in batch mode
status . line_buff = line_buff ;
status . file_name = source_name ;
glob_buffer . length ( 0 ) ; // Empty command buffer
error = read_lines ( 0 ) ; // Read lines from file
status = old_status ; // Continue as before
my_fclose ( sql_file , MYF ( 0 ) ) ;
batch_readline_end ( line_buff ) ;
return error ;
}
/* ARGSUSED */
static int
com_use ( String * buffer __attribute__ ( ( unused ) ) , char * line )
{
char * tmp ;
char buff [ 256 ] ;
2002-03-12 18:37:58 +01:00
while ( my_isspace ( system_charset_info , * line ) )
2000-07-31 21:29:14 +02:00
line + + ;
strnmov ( buff , line , sizeof ( buff ) - 1 ) ; // Don't destroy history
if ( buff [ 0 ] = = ' \\ ' ) // Short command
buff [ 1 ] = ' ' ;
2000-11-17 13:33:29 +01:00
tmp = ( char * ) strtok ( buff , " \t ; " ) ; // Skip connect command
2000-07-31 21:29:14 +02:00
if ( ! tmp | | ! ( tmp = ( char * ) strtok ( NullS , " \t ; " ) ) )
{
put_info ( " USE must be followed by a database name " , INFO_ERROR ) ;
return 0 ;
}
if ( ! current_db | | cmp_database ( current_db , tmp ) )
{
if ( one_database )
2002-04-02 19:29:53 +02:00
skip_updates = 1 ;
2000-07-31 21:29:14 +02:00
else
{
/*
reconnect once if connection is down or if connection was found to
be down during query
*/
if ( ! connected & & reconnect ( ) )
return status . batch ? 1 : - 1 ; // Fatal error
if ( mysql_select_db ( & mysql , tmp ) )
{
if ( mysql_errno ( & mysql ) ! = CR_SERVER_GONE_ERROR )
return put_info ( mysql_error ( & mysql ) , INFO_ERROR , mysql_errno ( & mysql ) ) ;
if ( reconnect ( ) )
return status . batch ? 1 : - 1 ; // Fatal error
if ( mysql_select_db ( & mysql , tmp ) )
return put_info ( mysql_error ( & mysql ) , INFO_ERROR , mysql_errno ( & mysql ) ) ;
}
2001-01-12 12:52:32 +01:00
my_free ( current_db , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
current_db = my_strdup ( tmp , MYF ( MY_WME ) ) ;
2000-07-31 21:29:14 +02:00
# ifdef HAVE_READLINE
2002-04-16 10:39:03 +02:00
build_completion_hash ( rehash , 1 ) ;
2000-07-31 21:29:14 +02:00
# endif
}
}
else
2002-04-02 19:29:53 +02:00
skip_updates = 0 ;
2000-07-31 21:29:14 +02:00
put_info ( " Database changed " , INFO_INFO ) ;
return 0 ;
}
static int
sql_real_connect ( char * host , char * database , char * user , char * password ,
uint silent )
{
2001-09-22 16:40:57 +02:00
mysql_close ( & mysql ) ;
connected = 0 ;
2000-07-31 21:29:14 +02:00
mysql_init ( & mysql ) ;
2000-11-18 01:15:06 +01:00
if ( opt_connect_timeout )
2000-11-27 01:28:41 +01:00
{
uint timeout = opt_connect_timeout ;
2000-11-18 01:15:06 +01:00
mysql_options ( & mysql , MYSQL_OPT_CONNECT_TIMEOUT ,
2000-11-27 01:28:41 +01:00
( char * ) & timeout ) ;
}
2000-07-31 21:29:14 +02:00
if ( opt_compress )
mysql_options ( & mysql , MYSQL_OPT_COMPRESS , NullS ) ;
2002-04-03 12:36:01 +02:00
if ( using_opt_local_infile )
mysql_options ( & mysql , MYSQL_OPT_LOCAL_INFILE , ( char * ) & opt_local_infile ) ;
2000-07-31 21:29:14 +02:00
# ifdef HAVE_OPENSSL
if ( opt_use_ssl )
mysql_ssl_set ( & mysql , opt_ssl_key , opt_ssl_cert , opt_ssl_ca ,
2001-09-30 04:46:20 +02:00
opt_ssl_capath , opt_ssl_cipher ) ;
2002-11-14 20:16:30 +01:00
# endif
if ( opt_protocol )
mysql_options ( & mysql , MYSQL_OPT_PROTOCOL , ( char * ) & opt_protocol ) ;
# ifdef HAVE_SMEM
if ( shared_memory_base_name )
mysql_options ( & mysql , MYSQL_SHARED_MEMORY_BASE_NAME , shared_memory_base_name ) ;
2000-07-31 21:29:14 +02:00
# endif
if ( safe_updates )
{
char init_command [ 100 ] ;
sprintf ( init_command ,
" SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%lu,SQL_MAX_JOIN_SIZE=%lu " ,
select_limit , max_join_size ) ;
mysql_options ( & mysql , MYSQL_INIT_COMMAND , init_command ) ;
}
2002-04-02 19:29:53 +02:00
if ( ! mysql_real_connect ( & mysql , host , user , password ,
database , opt_mysql_port , opt_mysql_unix_port ,
2000-07-31 21:29:14 +02:00
connect_flag ) )
{
if ( ! silent | |
( mysql_errno ( & mysql ) ! = CR_CONN_HOST_ERROR & &
mysql_errno ( & mysql ) ! = CR_CONNECTION_ERROR ) )
{
put_info ( mysql_error ( & mysql ) , INFO_ERROR , mysql_errno ( & mysql ) ) ;
( void ) fflush ( stdout ) ;
return ignore_errors ? - 1 : 1 ; // Abort
}
return - 1 ; // Retryable
}
connected = 1 ;
mysql . reconnect = info_flag ? 1 : 0 ; // We want to know if this happens
# ifdef HAVE_READLINE
2002-04-16 10:39:03 +02:00
build_completion_hash ( rehash , 1 ) ;
2000-07-31 21:29:14 +02:00
# endif
return 0 ;
}
static int
sql_connect ( char * host , char * database , char * user , char * password , uint silent )
{
bool message = 0 ;
uint count = 0 ;
int error ;
for ( ; ; )
{
if ( ( error = sql_real_connect ( host , database , user , password , wait_flag ) ) > = 0 )
{
if ( count )
{
2000-11-17 13:33:29 +01:00
tee_fputs ( " \n " , stderr ) ;
2000-07-31 21:29:14 +02:00
( void ) fflush ( stderr ) ;
}
return error ;
}
if ( ! wait_flag )
return ignore_errors ? - 1 : 1 ;
if ( ! message & & ! silent )
{
message = 1 ;
2000-11-17 13:33:29 +01:00
tee_fputs ( " Waiting " , stderr ) ; ( void ) fflush ( stderr ) ;
2000-07-31 21:29:14 +02:00
}
2001-01-17 13:47:33 +01:00
( void ) sleep ( wait_time ) ;
2000-07-31 21:29:14 +02:00
if ( ! silent )
{
putc ( ' . ' , stderr ) ; ( void ) fflush ( stderr ) ;
count + + ;
}
}
}
static int
com_status ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
{
2002-04-03 12:36:01 +02:00
const char * status ;
2000-11-17 13:33:29 +01:00
tee_puts ( " -------------- " , stdout ) ;
2000-07-31 21:29:14 +02:00
usage ( 1 ) ; /* Print version */
if ( connected )
{
MYSQL_RES * result ;
LINT_INIT ( result ) ;
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " \n Connection id: \t \t %ld \n " , mysql_thread_id ( & mysql ) ) ;
2000-07-31 21:29:14 +02:00
if ( ! mysql_query ( & mysql , " select DATABASE(),USER() " ) & &
( result = mysql_use_result ( & mysql ) ) )
{
MYSQL_ROW cur = mysql_fetch_row ( result ) ;
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " Current database: \t %s \n " , cur [ 0 ] ) ;
tee_fprintf ( stdout , " Current user: \t \t %s \n " , cur [ 1 ] ) ;
2000-07-31 21:29:14 +02:00
( void ) mysql_fetch_row ( result ) ; // Read eof
}
2002-04-22 22:36:34 +02:00
# ifdef HAVE_OPENSSL
if ( mysql . net . vio - > ssl_ & & SSL_get_cipher ( mysql . net . vio - > ssl_ ) )
2002-05-31 11:34:47 +02:00
tee_fprintf ( stdout , " SSL: \t \t \t Cipher in use is %s \n " ,
2002-04-22 22:36:34 +02:00
SSL_get_cipher ( mysql . net . vio - > ssl_ ) ) ;
else
# endif /* HAVE_OPENSSL */
2002-05-31 11:34:47 +02:00
tee_puts ( " SSL: \t \t \t Not in use " , stdout ) ;
2000-07-31 21:29:14 +02:00
}
else
{
vidattr ( A_BOLD ) ;
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " \n No connection \n " ) ;
2000-07-31 21:29:14 +02:00
vidattr ( A_NORMAL ) ;
return 0 ;
}
if ( skip_updates )
{
vidattr ( A_BOLD ) ;
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " \n All updates ignored to this database \n " ) ;
2000-07-31 21:29:14 +02:00
vidattr ( A_NORMAL ) ;
}
2000-11-17 13:33:29 +01:00
# ifndef __WIN__
tee_fprintf ( stdout , " Current pager: \t \t %s \n " , pager ) ;
2000-11-28 03:47:47 +01:00
tee_fprintf ( stdout , " Using outfile: \t \t '%s' \n " , opt_outfile ? outfile : " " ) ;
2000-11-17 13:33:29 +01:00
# endif
tee_fprintf ( stdout , " Server version: \t \t %s \n " , mysql_get_server_info ( & mysql ) ) ;
tee_fprintf ( stdout , " Protocol version: \t %d \n " , mysql_get_proto_info ( & mysql ) ) ;
tee_fprintf ( stdout , " Connection: \t \t %s \n " , mysql_get_host_info ( & mysql ) ) ;
2000-12-29 15:06:10 +01:00
tee_fprintf ( stdout , " Client characterset: \t %s \n " ,
2002-03-14 17:52:48 +01:00
system_charset_info - > name ) ;
2000-12-29 15:06:10 +01:00
tee_fprintf ( stdout , " Server characterset: \t %s \n " , mysql . charset - > name ) ;
2000-07-31 21:29:14 +02:00
if ( strstr ( mysql_get_host_info ( & mysql ) , " TCP/IP " ) | | ! mysql . unix_socket )
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " TCP port: \t \t %d \n " , mysql . port ) ;
2000-07-31 21:29:14 +02:00
else
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " UNIX socket: \t \t %s \n " , mysql . unix_socket ) ;
2000-11-28 03:47:47 +01:00
if ( mysql . net . compress )
tee_fprintf ( stdout , " Protocol: \t \t Compressed \n " ) ;
2000-07-31 21:29:14 +02:00
if ( ( status = mysql_stat ( & mysql ) ) & & ! mysql_error ( & mysql ) [ 0 ] )
{
ulong sec ;
2002-07-23 17:31:22 +02:00
char buff [ 40 ] ;
const char * pos = strchr ( status , ' ' ) ;
/* print label */
tee_fprintf ( stdout , " %.*s \t \t \t " , ( int ) ( pos - status ) , status ) ;
2000-07-31 21:29:14 +02:00
if ( ( status = str2int ( pos , 10 , 0 , LONG_MAX , ( long * ) & sec ) ) )
{
nice_time ( ( double ) sec , buff , 0 ) ;
2000-11-17 13:33:29 +01:00
tee_puts ( buff , stdout ) ; /* print nice time */
2000-07-31 21:29:14 +02:00
while ( * status = = ' ' ) status + + ; /* to next info */
}
if ( status )
{
2000-11-18 16:34:15 +01:00
tee_putc ( ' \n ' , stdout ) ;
2000-11-17 13:33:29 +01:00
tee_puts ( status , stdout ) ;
2000-07-31 21:29:14 +02:00
}
}
if ( safe_updates )
{
vidattr ( A_BOLD ) ;
2001-02-21 03:39:48 +01:00
tee_fprintf ( stdout , " \n Note that you are running in safe_update_mode: \n " ) ;
2000-07-31 21:29:14 +02:00
vidattr ( A_NORMAL ) ;
2000-11-17 13:33:29 +01:00
tee_fprintf ( stdout , " \
2001-02-21 03:39:48 +01:00
UPDATEs and DELETEs that don ' t use a key in the WHERE clause are not allowed . \ n \
( One can force an UPDATE / DELETE by adding LIMIT # at the end of the command . ) \ n \
SELECT has an automatic ' LIMIT % lu ' if LIMIT is not used . \ n \
2000-07-31 21:29:14 +02:00
Max number of examined row combination in a join is set to : % lu \ n \ n " ,
2001-02-21 03:39:48 +01:00
select_limit , max_join_size ) ;
2000-07-31 21:29:14 +02:00
}
2000-11-17 13:33:29 +01:00
tee_puts ( " -------------- \n " , stdout ) ;
2000-07-31 21:29:14 +02:00
return 0 ;
}
static int
put_info ( const char * str , INFO_TYPE info_type , uint error )
{
static int inited = 0 ;
2001-12-06 13:10:51 +01:00
2000-07-31 21:29:14 +02:00
if ( status . batch )
{
if ( info_type = = INFO_ERROR )
{
( void ) fflush ( stdout ) ;
fprintf ( stderr , " ERROR " ) ;
if ( error )
( void ) fprintf ( stderr , " %d " , error ) ;
2002-04-02 19:29:53 +02:00
if ( status . query_start_line & & line_numbers )
2000-07-31 21:29:14 +02:00
{
( void ) fprintf ( stderr , " at line %lu " , status . query_start_line ) ;
if ( status . file_name )
( void ) fprintf ( stderr , " in file: '%s' " , status . file_name ) ;
}
( void ) fprintf ( stderr , " : %s \n " , str ) ;
( void ) fflush ( stderr ) ;
if ( ! ignore_errors )
return 1 ;
}
else if ( info_type = = INFO_RESULT & & verbose > 1 )
2000-11-17 13:33:29 +01:00
tee_puts ( str , stdout ) ;
2000-07-31 21:29:14 +02:00
if ( unbuffered )
fflush ( stdout ) ;
return info_type = = INFO_ERROR ? - 1 : 0 ;
}
if ( ! opt_silent | | info_type = = INFO_ERROR )
{
if ( ! inited )
{
inited = 1 ;
# ifdef HAVE_SETUPTERM
( void ) setupterm ( ( char * ) 0 , 1 , ( int * ) 0 ) ;
# endif
}
if ( info_type = = INFO_ERROR )
{
2002-06-11 10:20:31 +02:00
if ( ! opt_nobeep )
2002-04-03 12:36:01 +02:00
putchar ( ' \007 ' ) ; /* This should make a bell */
2000-07-31 21:29:14 +02:00
vidattr ( A_STANDOUT ) ;
if ( error )
2000-11-17 13:33:29 +01:00
( void ) tee_fprintf ( stderr , " ERROR %d: " , error ) ;
2000-07-31 21:29:14 +02:00
else
2000-11-17 13:33:29 +01:00
tee_puts ( " ERROR: " , stdout ) ;
2000-07-31 21:29:14 +02:00
}
else
vidattr ( A_BOLD ) ;
2000-11-17 13:33:29 +01:00
( void ) tee_puts ( str , stdout ) ;
2000-07-31 21:29:14 +02:00
vidattr ( A_NORMAL ) ;
}
if ( unbuffered )
fflush ( stdout ) ;
return info_type = = INFO_ERROR ? - 1 : 0 ;
}
2000-11-17 13:33:29 +01:00
2000-07-31 21:29:14 +02:00
static void remove_cntrl ( String & buffer )
{
char * start , * end ;
end = ( start = ( char * ) buffer . ptr ( ) ) + buffer . length ( ) ;
2002-03-12 18:37:58 +01:00
while ( start < end & & ! my_isgraph ( system_charset_info , end [ - 1 ] ) )
2000-07-31 21:29:14 +02:00
end - - ;
buffer . length ( ( uint ) ( end - start ) ) ;
}
2000-11-17 13:33:29 +01:00
void tee_fprintf ( FILE * file , const char * fmt , . . . )
{
va_list args ;
va_start ( args , fmt ) ;
2000-11-18 01:15:06 +01:00
( void ) vfprintf ( file , fmt , args ) ;
2001-08-22 00:45:07 +02:00
# ifdef OS2
fflush ( file ) ;
# endif
2000-11-17 13:33:29 +01:00
if ( opt_outfile )
2000-11-18 01:15:06 +01:00
( void ) vfprintf ( OUTFILE , fmt , args ) ;
2000-11-17 13:33:29 +01:00
va_end ( args ) ;
}
void tee_fputs ( const char * s , FILE * file )
{
fputs ( s , file ) ;
2001-08-22 00:45:07 +02:00
# ifdef OS2
fflush ( file ) ;
# endif
2000-11-17 13:33:29 +01:00
if ( opt_outfile )
fputs ( s , OUTFILE ) ;
}
void tee_puts ( const char * s , FILE * file )
{
fputs ( s , file ) ;
fputs ( " \n " , file ) ;
2001-08-22 00:45:07 +02:00
# ifdef OS2
fflush ( file ) ;
# endif
2000-11-17 13:33:29 +01:00
if ( opt_outfile )
{
fputs ( s , OUTFILE ) ;
fputs ( " \n " , OUTFILE ) ;
}
}
2000-11-18 16:34:15 +01:00
void tee_putc ( int c , FILE * file )
{
putc ( c , file ) ;
2001-08-22 00:45:07 +02:00
# ifdef OS2
fflush ( file ) ;
# endif
2000-11-18 16:34:15 +01:00
if ( opt_outfile )
putc ( c , OUTFILE ) ;
}
2001-08-22 00:45:07 +02:00
# if defined( __WIN__) || defined( OS2)
2000-07-31 21:29:14 +02:00
# include <time.h>
# else
# include <sys/times.h>
2002-06-20 22:26:39 +02:00
# ifdef _SC_CLK_TCK // For mit-pthreads
2000-07-31 21:29:14 +02:00
# undef CLOCKS_PER_SEC
# define CLOCKS_PER_SEC (sysconf(_SC_CLK_TCK))
# endif
2002-06-20 22:26:39 +02:00
# endif
2000-07-31 21:29:14 +02:00
static ulong start_timer ( void )
{
2001-08-22 00:45:07 +02:00
# if defined( __WIN__) || defined( OS2)
2000-07-31 21:29:14 +02:00
return clock ( ) ;
# else
struct tms tms_tmp ;
return times ( & tms_tmp ) ;
# endif
}
static void nice_time ( double sec , char * buff , bool part_second )
{
ulong tmp ;
if ( sec > = 3600.0 * 24 )
{
tmp = ( ulong ) floor ( sec / ( 3600.0 * 24 ) ) ;
sec - = 3600.0 * 24 * tmp ;
buff = int2str ( ( long ) tmp , buff , 10 ) ;
buff = strmov ( buff , tmp > 1 ? " days " : " day " ) ;
}
if ( sec > = 3600.0 )
{
tmp = ( ulong ) floor ( sec / 3600.0 ) ;
sec - = 3600.0 * tmp ;
buff = int2str ( ( long ) tmp , buff , 10 ) ;
buff = strmov ( buff , tmp > 1 ? " hours " : " hour " ) ;
}
if ( sec > = 60.0 )
{
tmp = ( ulong ) floor ( sec / 60.0 ) ;
sec - = 60.0 * tmp ;
buff = int2str ( ( long ) tmp , buff , 10 ) ;
buff = strmov ( buff , " min " ) ;
}
if ( part_second )
sprintf ( buff , " %.2f sec " , sec ) ;
else
sprintf ( buff , " %d sec " , ( int ) sec ) ;
}
static void end_timer ( ulong start_time , char * buff )
{
nice_time ( ( double ) ( start_timer ( ) - start_time ) /
CLOCKS_PER_SEC , buff , 1 ) ;
}
static void mysql_end_timer ( ulong start_time , char * buff )
{
buff [ 0 ] = ' ' ;
buff [ 1 ] = ' ( ' ;
end_timer ( start_time , buff + 2 ) ;
strmov ( strend ( buff ) , " ) " ) ;
}
2002-06-11 10:20:31 +02:00
static const char * construct_prompt ( )
{
2002-04-03 12:36:01 +02:00
//erase the old prompt
processed_prompt . free ( ) ;
//get the date struct
time_t lclock = time ( NULL ) ;
struct tm * t = localtime ( & lclock ) ;
//parse thru the settings for the prompt
2002-06-11 10:20:31 +02:00
for ( char * c = current_prompt ; * c ; * c + + )
{
if ( * c ! = PROMPT_CHAR )
2002-04-03 12:36:01 +02:00
processed_prompt . append ( * c ) ;
2002-06-11 10:20:31 +02:00
else
{
2002-04-03 12:36:01 +02:00
switch ( * + + c ) {
case ' \0 ' :
//stop it from going beyond if ends with %
c - - ;
break ;
case ' c ' :
add_int_to_prompt ( + + prompt_counter ) ;
break ;
case ' v ' :
processed_prompt . append ( mysql_get_server_info ( & mysql ) ) ;
break ;
case ' d ' :
processed_prompt . append ( current_db ? current_db : " (none) " ) ;
break ;
case ' h ' :
{
const char * prompt = mysql_get_host_info ( & mysql ) ;
if ( strstr ( prompt , " Localhost " ) )
processed_prompt . append ( " localhost " ) ;
else
{
const char * end = strcend ( prompt , ' ' ) ;
processed_prompt . append ( prompt , ( uint ) ( end - prompt ) ) ;
}
break ;
}
case ' p ' :
if ( strstr ( mysql_get_host_info ( & mysql ) , " TCP/IP " ) | |
! mysql . unix_socket )
add_int_to_prompt ( mysql . port ) ;
else
processed_prompt . append ( strrchr ( mysql . unix_socket , ' / ' ) + 1 ) ;
break ;
case ' U ' :
if ( ! full_username )
init_username ( ) ;
processed_prompt . append ( full_username ) ;
break ;
case ' u ' :
if ( ! full_username )
init_username ( ) ;
processed_prompt . append ( part_username ) ;
break ;
case PROMPT_CHAR :
processed_prompt . append ( PROMPT_CHAR ) ;
break ;
case ' n ' :
processed_prompt . append ( ' \n ' ) ;
break ;
case ' ' :
case ' _ ' :
processed_prompt . append ( ' ' ) ;
break ;
case ' R ' :
add_int_to_prompt ( t - > tm_hour ) ;
break ;
case ' r ' :
int getHour ;
getHour = t - > tm_hour % 12 ;
if ( getHour = = 0 )
getHour = 12 ;
add_int_to_prompt ( getHour ) ;
break ;
case ' m ' :
if ( t - > tm_min < 10 )
processed_prompt . append ( ' 0 ' ) ;
add_int_to_prompt ( t - > tm_min ) ;
break ;
case ' y ' :
int getYear ;
getYear = t - > tm_year % 100 ;
if ( getYear < 10 )
processed_prompt . append ( ' 0 ' ) ;
add_int_to_prompt ( getYear ) ;
break ;
case ' Y ' :
add_int_to_prompt ( t - > tm_year + 1900 ) ;
break ;
case ' D ' :
char * dateTime ;
time_t lclock ;
lclock = time ( NULL ) ;
dateTime = ctime ( & lclock ) ;
processed_prompt . append ( strtok ( dateTime , " \n " ) ) ;
break ;
case ' s ' :
add_int_to_prompt ( t - > tm_sec ) ;
break ;
case ' w ' :
processed_prompt . append ( day_names [ t - > tm_wday ] ) ;
break ;
case ' P ' :
processed_prompt . append ( t - > tm_hour < 12 ? " am " : " pm " ) ;
break ;
case ' o ' :
add_int_to_prompt ( t - > tm_mon + 1 ) ;
break ;
case ' O ' :
processed_prompt . append ( month_names [ t - > tm_mon ] ) ;
break ;
case ' \' ' :
processed_prompt . append ( " ' " ) ;
break ;
case ' " ' :
processed_prompt . append ( ' " ' ) ;
break ;
case ' S ' :
processed_prompt . append ( ' ; ' ) ;
break ;
case ' t ' :
processed_prompt . append ( ' \t ' ) ;
break ;
default :
processed_prompt . append ( c ) ;
}
}
}
processed_prompt . append ( ' \0 ' ) ;
return processed_prompt . ptr ( ) ;
}
2002-06-11 10:20:31 +02:00
static void add_int_to_prompt ( int toadd )
{
2002-04-03 12:36:01 +02:00
char buffer [ 16 ] ;
int10_to_str ( toadd , buffer , 10 ) ;
processed_prompt . append ( buffer ) ;
}
2002-06-11 10:20:31 +02:00
static void init_username ( )
{
2002-04-03 12:36:01 +02:00
my_free ( full_username , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
my_free ( part_username , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
MYSQL_RES * result ;
LINT_INIT ( result ) ;
if ( ! mysql_query ( & mysql , " select USER() " ) & &
( result = mysql_use_result ( & mysql ) ) )
2002-06-11 10:20:31 +02:00
{
MYSQL_ROW cur = mysql_fetch_row ( result ) ;
full_username = my_strdup ( cur [ 0 ] , MYF ( MY_WME ) ) ;
part_username = my_strdup ( strtok ( cur [ 0 ] , " @ " ) , MYF ( MY_WME ) ) ;
( void ) mysql_fetch_row ( result ) ; // Read eof
}
2002-04-03 12:36:01 +02:00
}
2002-06-11 10:20:31 +02:00
static int com_prompt ( String * buffer , char * line )
{
char * ptr = strchr ( line , ' ' ) ;
2002-04-03 12:36:01 +02:00
prompt_counter = 0 ;
my_free ( current_prompt , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
2002-06-11 10:20:31 +02:00
current_prompt = my_strdup ( ptr ? ptr + 1 : default_prompt , MYF ( MY_WME ) ) ;
if ( ! ptr )
2002-04-03 12:36:01 +02:00
tee_fprintf ( stdout , " Returning to default PROMPT of %s \n " , default_prompt ) ;
else
tee_fprintf ( stdout , " PROMPT set to '%s' \n " , current_prompt ) ;
return 0 ;
}
2001-09-22 16:40:57 +02:00
# ifndef EMBEDDED_LIBRARY
2000-07-31 21:29:14 +02:00
/* Keep sql_string library happy */
gptr sql_alloc ( unsigned int Size )
{
return my_malloc ( Size , MYF ( MY_WME ) ) ;
}
void sql_element_free ( void * ptr )
{
my_free ( ( gptr ) ptr , MYF ( 0 ) ) ;
}
2001-09-22 16:40:57 +02:00
# endif /* EMBEDDED_LIBRARY */
2002-10-28 14:44:19 +01:00