2008-01-25 16:53:21 +01:00
/* Copyright (C) 2000-2008 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
2006-12-23 20:17:15 +01:00
the Free Software Foundation ; version 2 of the License .
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 >
2004-03-03 21:54:37 +01:00
* Harrison Fisk < harrison @ mysql . com >
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
2003-04-07 02:14:36 +02:00
# if defined(USE_LIBEDIT_INTERFACE) && defined(HAVE_LOCALE_H)
# include <locale.h>
# endif
2005-07-18 14:33:18 +02:00
const char * VER = " 14.12 " ;
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
2006-09-29 20:52:48 +02:00
/* Buffer to hold 'version' and 'version_comment' */
# define MAX_SERVER_VERSION_LENGTH 128
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>
2003-01-28 07:38:28 +01:00
# elif !defined(__NETWARE__)
2000-07-31 21:29:14 +02:00
# 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
2003-03-16 08:20:45 +01:00
# define cmp_database(cs,A,B) my_strcasecmp((cs), (A), (B))
2000-07-31 21:29:14 +02:00
# else
2003-03-16 08:20:45 +01:00
# define cmp_database(cs,A,B) strcmp((A),(B))
2000-07-31 21:29:14 +02:00
# endif
2003-01-28 07:38:28 +01:00
# if !defined( __WIN__) && !defined( OS2) && !defined(__NETWARE__) && (!defined(HAVE_mit_thread) || !defined(THREAD))
# define USE_POPEN
# endif
2000-07-31 21:29:14 +02:00
# include "completion_hash.h"
2002-04-03 12:36:01 +02:00
# define PROMPT_CHAR '\\'
2003-04-23 02:29:03 +02:00
# define DEFAULT_DELIMITER ";"
2002-04-03 12:36:01 +02:00
2009-03-18 09:18:24 +01:00
# define MAX_BATCH_BUFFER_SIZE (1024L * 1024L)
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 ,
2006-12-14 23:51:37 +01:00
opt_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 ,
2003-08-18 23:08:08 +02:00
tty_password = 0 , opt_nobeep = 0 , opt_reconnect = 1 ,
2004-01-14 03:58:37 +01:00
default_charset_used = 0 , opt_secure_auth = 0 ,
2005-04-05 15:30:17 +02:00
default_pager_set = 0 , opt_sigint_ignore = 0 ,
2009-05-07 19:28:29 +02:00
show_warnings = 0 , ignore_spaces = 0 ;
2006-08-10 03:46:46 +02:00
static volatile int executing_query = 0 , interrupted_query = 0 ;
2007-11-02 11:40:34 +01:00
static my_bool preserve_comments = 0 ;
2004-05-26 18:40:27 +02:00
static ulong opt_max_allowed_packet , opt_net_buffer_length ;
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 ,
2003-04-23 02:29:03 +02:00
* current_prompt = 0 , * delimiter_str = 0 ,
2003-05-28 13:23:04 +02:00
* default_charset = ( char * ) MYSQL_DEFAULT_CHARSET_NAME ;
2000-07-31 21:29:14 +02:00
static char * histfile ;
2005-01-25 17:32:09 +01:00
static char * histfile_tmp ;
2000-07-31 21:29:14 +02:00
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
" & " , " & " ,
" < " , " < " ,
2005-01-25 23:25:40 +01:00
" > " , " > " ,
" \" " , " " " ,
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 ;
2003-04-23 02:29:03 +02:00
static char delimiter [ 16 ] = DEFAULT_DELIMITER ;
static uint delimiter_length = 1 ;
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 ;
2003-03-16 08:20:45 +01:00
static CHARSET_INFO * charset_info = & my_charset_latin1 ;
2005-01-14 22:46:04 +01:00
2000-07-31 21:29:14 +02:00
# include "sslopt-vars.h"
const char * default_dbug_option = " d:t:o,/tmp/mysql.trace " ;
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 ) ;
2006-04-04 23:35:07 +02:00
static void tee_print_sized_data ( const char * , unsigned int , unsigned int , bool ) ;
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 * ) ,
2006-02-09 15:23:09 +01:00
com_notee ( String * str , char * ) , com_charset ( String * str , char * ) ,
2005-04-05 15:30:17 +02:00
com_prompt ( String * str , char * ) , com_delimiter ( String * str , char * ) ,
com_warnings ( String * str , char * ) , com_nowarnings ( String * str , char * ) ;
2000-07-31 21:29:14 +02:00
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
2000-11-22 02:45:02 +01:00
static int com_nopager ( String * str , char * ) , com_pager ( String * str , char * ) ,
2003-01-28 07:38:28 +01:00
com_edit ( String * str , char * ) , com_shell ( String * str , char * ) ;
2000-11-22 02:45:02 +01:00
# endif
2005-08-09 21:17:28 +02:00
static int read_and_execute ( bool interactive ) ;
2000-07-31 21:29:14 +02:00
static int sql_connect ( char * host , char * database , char * user , char * password ,
uint silent ) ;
2006-09-29 20:52:48 +02:00
static const char * server_version_string ( MYSQL * mysql ) ;
2003-06-04 17:28:51 +02:00
static int put_info ( const char * str , INFO_TYPE info , uint error = 0 ,
const char * sql_state = 0 ) ;
static int put_error ( MYSQL * mysql ) ;
2000-07-31 21:29:14 +02:00
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 ( ) ;
2003-01-28 07:38:28 +01:00
static void init_tee ( const 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 ( ) ;
2002-12-25 22:57:01 +01:00
static char * get_arg ( char * line , my_bool get_next_arg ) ;
2002-04-03 12:36:01 +02:00
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
{ " ? " , ' ? ' , com_help , 1 , " Synonym for `help'. " } ,
2009-04-14 16:16:30 +02:00
{ " clear " , ' c ' , com_clear , 0 , " Clear the current input statement. " } ,
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. " } ,
2003-12-30 16:58:39 +01:00
{ " delimiter " , ' d ' , com_delimiter , 1 ,
2009-02-18 11:18:38 +01:00
" Set statement delimiter. " } ,
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
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. " } ,
2003-12-30 16:58:39 +01:00
{ " help " , ' h ' , com_help , 1 , " Display this help. " } ,
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
2000-11-17 13:33:29 +01:00
{ " nopager " , ' n ' , com_nopager , 0 , " Disable pager, print to stdout. " } ,
# endif
{ " notee " , ' t ' , com_notee , 0 , " Don't write into outfile. " } ,
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
2000-11-17 13:33:29 +01:00
{ " 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 ,
2005-12-20 19:47:44 +01:00
" Execute an SQL script file. Takes a file name as an argument. " } ,
2000-11-17 13:33:29 +01:00
{ " status " , ' s ' , com_status , 0 , " Get status information from the server. " } ,
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
2001-11-06 22:00:03 +01:00
{ " 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. " } ,
2006-02-09 15:23:09 +01:00
{ " charset " , ' C ' , com_charset , 1 ,
" Switch to another charset. Might be needed for processing binlog with multi-byte charsets. " } ,
2005-04-14 15:07:08 +02:00
{ " warnings " , ' W ' , com_warnings , 0 ,
2005-04-05 15:30:17 +02:00
" Show warnings after every statement. " } ,
2005-04-14 15:07:08 +02:00
{ " nowarning " , ' w ' , com_nowarnings , 0 ,
2005-04-05 15:30:17 +02:00
" Don't show warnings after every statement. " } ,
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 , " " } ,
{ " 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 , " " } ,
2008-01-30 22:51:39 +01:00
/* generated 2006-12-28. Refresh occasionally from lexer. */
{ " ACTION " , 0 , 0 , 0 , " " } ,
{ " ADD " , 0 , 0 , 0 , " " } ,
{ " AFTER " , 0 , 0 , 0 , " " } ,
{ " AGAINST " , 0 , 0 , 0 , " " } ,
{ " AGGREGATE " , 0 , 0 , 0 , " " } ,
{ " ALL " , 0 , 0 , 0 , " " } ,
{ " ALGORITHM " , 0 , 0 , 0 , " " } ,
{ " ALTER " , 0 , 0 , 0 , " " } ,
{ " ANALYZE " , 0 , 0 , 0 , " " } ,
{ " AND " , 0 , 0 , 0 , " " } ,
{ " ANY " , 0 , 0 , 0 , " " } ,
{ " AS " , 0 , 0 , 0 , " " } ,
{ " ASC " , 0 , 0 , 0 , " " } ,
{ " ASCII " , 0 , 0 , 0 , " " } ,
{ " ASENSITIVE " , 0 , 0 , 0 , " " } ,
{ " AUTO_INCREMENT " , 0 , 0 , 0 , " " } ,
{ " AVG " , 0 , 0 , 0 , " " } ,
{ " AVG_ROW_LENGTH " , 0 , 0 , 0 , " " } ,
{ " BACKUP " , 0 , 0 , 0 , " " } ,
{ " BDB " , 0 , 0 , 0 , " " } ,
{ " BEFORE " , 0 , 0 , 0 , " " } ,
{ " BEGIN " , 0 , 0 , 0 , " " } ,
{ " BERKELEYDB " , 0 , 0 , 0 , " " } ,
{ " BETWEEN " , 0 , 0 , 0 , " " } ,
{ " BIGINT " , 0 , 0 , 0 , " " } ,
{ " BINARY " , 0 , 0 , 0 , " " } ,
{ " BINLOG " , 0 , 0 , 0 , " " } ,
{ " BIT " , 0 , 0 , 0 , " " } ,
{ " BLOB " , 0 , 0 , 0 , " " } ,
{ " BOOL " , 0 , 0 , 0 , " " } ,
{ " BOOLEAN " , 0 , 0 , 0 , " " } ,
{ " BOTH " , 0 , 0 , 0 , " " } ,
{ " BTREE " , 0 , 0 , 0 , " " } ,
{ " BY " , 0 , 0 , 0 , " " } ,
{ " BYTE " , 0 , 0 , 0 , " " } ,
{ " CACHE " , 0 , 0 , 0 , " " } ,
{ " CALL " , 0 , 0 , 0 , " " } ,
{ " CASCADE " , 0 , 0 , 0 , " " } ,
{ " CASCADED " , 0 , 0 , 0 , " " } ,
{ " CASE " , 0 , 0 , 0 , " " } ,
{ " CHAIN " , 0 , 0 , 0 , " " } ,
{ " CHANGE " , 0 , 0 , 0 , " " } ,
{ " CHANGED " , 0 , 0 , 0 , " " } ,
{ " CHAR " , 0 , 0 , 0 , " " } ,
{ " CHARACTER " , 0 , 0 , 0 , " " } ,
{ " CHARSET " , 0 , 0 , 0 , " " } ,
{ " CHECK " , 0 , 0 , 0 , " " } ,
{ " CHECKSUM " , 0 , 0 , 0 , " " } ,
{ " CIPHER " , 0 , 0 , 0 , " " } ,
{ " CLIENT " , 0 , 0 , 0 , " " } ,
{ " CLOSE " , 0 , 0 , 0 , " " } ,
{ " CODE " , 0 , 0 , 0 , " " } ,
{ " COLLATE " , 0 , 0 , 0 , " " } ,
{ " COLLATION " , 0 , 0 , 0 , " " } ,
{ " COLUMN " , 0 , 0 , 0 , " " } ,
{ " COLUMNS " , 0 , 0 , 0 , " " } ,
{ " COMMENT " , 0 , 0 , 0 , " " } ,
{ " COMMIT " , 0 , 0 , 0 , " " } ,
{ " COMMITTED " , 0 , 0 , 0 , " " } ,
{ " COMPACT " , 0 , 0 , 0 , " " } ,
{ " COMPRESSED " , 0 , 0 , 0 , " " } ,
{ " CONCURRENT " , 0 , 0 , 0 , " " } ,
{ " CONDITION " , 0 , 0 , 0 , " " } ,
{ " CONNECTION " , 0 , 0 , 0 , " " } ,
{ " CONSISTENT " , 0 , 0 , 0 , " " } ,
{ " CONSTRAINT " , 0 , 0 , 0 , " " } ,
{ " CONTAINS " , 0 , 0 , 0 , " " } ,
{ " CONTINUE " , 0 , 0 , 0 , " " } ,
{ " CONVERT " , 0 , 0 , 0 , " " } ,
{ " CREATE " , 0 , 0 , 0 , " " } ,
{ " CROSS " , 0 , 0 , 0 , " " } ,
{ " CUBE " , 0 , 0 , 0 , " " } ,
{ " CURRENT_DATE " , 0 , 0 , 0 , " " } ,
{ " CURRENT_TIME " , 0 , 0 , 0 , " " } ,
{ " CURRENT_TIMESTAMP " , 0 , 0 , 0 , " " } ,
{ " CURRENT_USER " , 0 , 0 , 0 , " " } ,
{ " CURSOR " , 0 , 0 , 0 , " " } ,
{ " DATA " , 0 , 0 , 0 , " " } ,
{ " DATABASE " , 0 , 0 , 0 , " " } ,
{ " DATABASES " , 0 , 0 , 0 , " " } ,
{ " DATE " , 0 , 0 , 0 , " " } ,
{ " DATETIME " , 0 , 0 , 0 , " " } ,
{ " DAY " , 0 , 0 , 0 , " " } ,
{ " DAY_HOUR " , 0 , 0 , 0 , " " } ,
{ " DAY_MICROSECOND " , 0 , 0 , 0 , " " } ,
{ " DAY_MINUTE " , 0 , 0 , 0 , " " } ,
{ " DAY_SECOND " , 0 , 0 , 0 , " " } ,
{ " DEALLOCATE " , 0 , 0 , 0 , " " } ,
{ " DEC " , 0 , 0 , 0 , " " } ,
{ " DECIMAL " , 0 , 0 , 0 , " " } ,
{ " DECLARE " , 0 , 0 , 0 , " " } ,
{ " DEFAULT " , 0 , 0 , 0 , " " } ,
{ " DEFINER " , 0 , 0 , 0 , " " } ,
{ " DELAYED " , 0 , 0 , 0 , " " } ,
{ " DELAY_KEY_WRITE " , 0 , 0 , 0 , " " } ,
{ " DELETE " , 0 , 0 , 0 , " " } ,
{ " DESC " , 0 , 0 , 0 , " " } ,
{ " DESCRIBE " , 0 , 0 , 0 , " " } ,
{ " DES_KEY_FILE " , 0 , 0 , 0 , " " } ,
{ " DETERMINISTIC " , 0 , 0 , 0 , " " } ,
{ " DIRECTORY " , 0 , 0 , 0 , " " } ,
{ " DISABLE " , 0 , 0 , 0 , " " } ,
{ " DISCARD " , 0 , 0 , 0 , " " } ,
{ " DISTINCT " , 0 , 0 , 0 , " " } ,
{ " DISTINCTROW " , 0 , 0 , 0 , " " } ,
{ " DIV " , 0 , 0 , 0 , " " } ,
{ " DO " , 0 , 0 , 0 , " " } ,
{ " DOUBLE " , 0 , 0 , 0 , " " } ,
{ " DROP " , 0 , 0 , 0 , " " } ,
{ " DUAL " , 0 , 0 , 0 , " " } ,
{ " DUMPFILE " , 0 , 0 , 0 , " " } ,
{ " DUPLICATE " , 0 , 0 , 0 , " " } ,
{ " DYNAMIC " , 0 , 0 , 0 , " " } ,
{ " EACH " , 0 , 0 , 0 , " " } ,
{ " ELSE " , 0 , 0 , 0 , " " } ,
{ " ELSEIF " , 0 , 0 , 0 , " " } ,
{ " ENABLE " , 0 , 0 , 0 , " " } ,
{ " ENCLOSED " , 0 , 0 , 0 , " " } ,
{ " END " , 0 , 0 , 0 , " " } ,
{ " ENGINE " , 0 , 0 , 0 , " " } ,
{ " ENGINES " , 0 , 0 , 0 , " " } ,
{ " ENUM " , 0 , 0 , 0 , " " } ,
{ " ERRORS " , 0 , 0 , 0 , " " } ,
{ " ESCAPE " , 0 , 0 , 0 , " " } ,
{ " ESCAPED " , 0 , 0 , 0 , " " } ,
{ " EVENTS " , 0 , 0 , 0 , " " } ,
{ " EXECUTE " , 0 , 0 , 0 , " " } ,
{ " EXISTS " , 0 , 0 , 0 , " " } ,
{ " EXIT " , 0 , 0 , 0 , " " } ,
{ " EXPANSION " , 0 , 0 , 0 , " " } ,
{ " EXPLAIN " , 0 , 0 , 0 , " " } ,
{ " EXTENDED " , 0 , 0 , 0 , " " } ,
{ " FALSE " , 0 , 0 , 0 , " " } ,
{ " FAST " , 0 , 0 , 0 , " " } ,
{ " FETCH " , 0 , 0 , 0 , " " } ,
{ " FIELDS " , 0 , 0 , 0 , " " } ,
{ " FILE " , 0 , 0 , 0 , " " } ,
{ " FIRST " , 0 , 0 , 0 , " " } ,
{ " FIXED " , 0 , 0 , 0 , " " } ,
{ " FLOAT " , 0 , 0 , 0 , " " } ,
{ " FLOAT4 " , 0 , 0 , 0 , " " } ,
{ " FLOAT8 " , 0 , 0 , 0 , " " } ,
{ " FLUSH " , 0 , 0 , 0 , " " } ,
{ " FOR " , 0 , 0 , 0 , " " } ,
{ " FORCE " , 0 , 0 , 0 , " " } ,
{ " FOREIGN " , 0 , 0 , 0 , " " } ,
{ " FOUND " , 0 , 0 , 0 , " " } ,
{ " FRAC_SECOND " , 0 , 0 , 0 , " " } ,
{ " FROM " , 0 , 0 , 0 , " " } ,
{ " FULL " , 0 , 0 , 0 , " " } ,
{ " FULLTEXT " , 0 , 0 , 0 , " " } ,
{ " FUNCTION " , 0 , 0 , 0 , " " } ,
{ " GEOMETRY " , 0 , 0 , 0 , " " } ,
{ " GEOMETRYCOLLECTION " , 0 , 0 , 0 , " " } ,
{ " GET_FORMAT " , 0 , 0 , 0 , " " } ,
{ " GLOBAL " , 0 , 0 , 0 , " " } ,
{ " GRANT " , 0 , 0 , 0 , " " } ,
{ " GRANTS " , 0 , 0 , 0 , " " } ,
{ " GROUP " , 0 , 0 , 0 , " " } ,
{ " HANDLER " , 0 , 0 , 0 , " " } ,
{ " HASH " , 0 , 0 , 0 , " " } ,
{ " HAVING " , 0 , 0 , 0 , " " } ,
{ " HELP " , 0 , 0 , 0 , " " } ,
{ " HIGH_PRIORITY " , 0 , 0 , 0 , " " } ,
{ " HOSTS " , 0 , 0 , 0 , " " } ,
{ " HOUR " , 0 , 0 , 0 , " " } ,
{ " HOUR_MICROSECOND " , 0 , 0 , 0 , " " } ,
{ " HOUR_MINUTE " , 0 , 0 , 0 , " " } ,
{ " HOUR_SECOND " , 0 , 0 , 0 , " " } ,
{ " IDENTIFIED " , 0 , 0 , 0 , " " } ,
{ " IF " , 0 , 0 , 0 , " " } ,
{ " IGNORE " , 0 , 0 , 0 , " " } ,
{ " IMPORT " , 0 , 0 , 0 , " " } ,
{ " IN " , 0 , 0 , 0 , " " } ,
{ " INDEX " , 0 , 0 , 0 , " " } ,
{ " INDEXES " , 0 , 0 , 0 , " " } ,
{ " INFILE " , 0 , 0 , 0 , " " } ,
{ " INNER " , 0 , 0 , 0 , " " } ,
{ " INNOBASE " , 0 , 0 , 0 , " " } ,
{ " INNODB " , 0 , 0 , 0 , " " } ,
{ " INOUT " , 0 , 0 , 0 , " " } ,
{ " INSENSITIVE " , 0 , 0 , 0 , " " } ,
{ " INSERT " , 0 , 0 , 0 , " " } ,
{ " INSERT_METHOD " , 0 , 0 , 0 , " " } ,
{ " INT " , 0 , 0 , 0 , " " } ,
{ " INT1 " , 0 , 0 , 0 , " " } ,
{ " INT2 " , 0 , 0 , 0 , " " } ,
{ " INT3 " , 0 , 0 , 0 , " " } ,
{ " INT4 " , 0 , 0 , 0 , " " } ,
{ " INT8 " , 0 , 0 , 0 , " " } ,
{ " INTEGER " , 0 , 0 , 0 , " " } ,
{ " INTERVAL " , 0 , 0 , 0 , " " } ,
{ " INTO " , 0 , 0 , 0 , " " } ,
{ " IO_THREAD " , 0 , 0 , 0 , " " } ,
{ " IS " , 0 , 0 , 0 , " " } ,
{ " ISOLATION " , 0 , 0 , 0 , " " } ,
{ " ISSUER " , 0 , 0 , 0 , " " } ,
{ " ITERATE " , 0 , 0 , 0 , " " } ,
{ " INVOKER " , 0 , 0 , 0 , " " } ,
{ " JOIN " , 0 , 0 , 0 , " " } ,
{ " KEY " , 0 , 0 , 0 , " " } ,
{ " KEYS " , 0 , 0 , 0 , " " } ,
{ " KILL " , 0 , 0 , 0 , " " } ,
{ " LANGUAGE " , 0 , 0 , 0 , " " } ,
{ " LAST " , 0 , 0 , 0 , " " } ,
{ " LEADING " , 0 , 0 , 0 , " " } ,
{ " LEAVE " , 0 , 0 , 0 , " " } ,
{ " LEAVES " , 0 , 0 , 0 , " " } ,
{ " LEFT " , 0 , 0 , 0 , " " } ,
{ " LEVEL " , 0 , 0 , 0 , " " } ,
{ " LIKE " , 0 , 0 , 0 , " " } ,
{ " LIMIT " , 0 , 0 , 0 , " " } ,
{ " LINES " , 0 , 0 , 0 , " " } ,
{ " LINESTRING " , 0 , 0 , 0 , " " } ,
{ " LOAD " , 0 , 0 , 0 , " " } ,
{ " LOCAL " , 0 , 0 , 0 , " " } ,
{ " LOCALTIME " , 0 , 0 , 0 , " " } ,
{ " LOCALTIMESTAMP " , 0 , 0 , 0 , " " } ,
{ " LOCK " , 0 , 0 , 0 , " " } ,
{ " LOCKS " , 0 , 0 , 0 , " " } ,
{ " LOGS " , 0 , 0 , 0 , " " } ,
{ " LONG " , 0 , 0 , 0 , " " } ,
{ " LONGBLOB " , 0 , 0 , 0 , " " } ,
{ " LONGTEXT " , 0 , 0 , 0 , " " } ,
{ " LOOP " , 0 , 0 , 0 , " " } ,
{ " LOW_PRIORITY " , 0 , 0 , 0 , " " } ,
{ " MASTER " , 0 , 0 , 0 , " " } ,
{ " MASTER_CONNECT_RETRY " , 0 , 0 , 0 , " " } ,
{ " MASTER_HOST " , 0 , 0 , 0 , " " } ,
{ " MASTER_LOG_FILE " , 0 , 0 , 0 , " " } ,
{ " MASTER_LOG_POS " , 0 , 0 , 0 , " " } ,
{ " MASTER_PASSWORD " , 0 , 0 , 0 , " " } ,
{ " MASTER_PORT " , 0 , 0 , 0 , " " } ,
{ " MASTER_SERVER_ID " , 0 , 0 , 0 , " " } ,
{ " MASTER_SSL " , 0 , 0 , 0 , " " } ,
{ " MASTER_SSL_CA " , 0 , 0 , 0 , " " } ,
{ " MASTER_SSL_CAPATH " , 0 , 0 , 0 , " " } ,
{ " MASTER_SSL_CERT " , 0 , 0 , 0 , " " } ,
{ " MASTER_SSL_CIPHER " , 0 , 0 , 0 , " " } ,
{ " MASTER_SSL_KEY " , 0 , 0 , 0 , " " } ,
{ " MASTER_USER " , 0 , 0 , 0 , " " } ,
{ " MATCH " , 0 , 0 , 0 , " " } ,
{ " MAX_CONNECTIONS_PER_HOUR " , 0 , 0 , 0 , " " } ,
{ " MAX_QUERIES_PER_HOUR " , 0 , 0 , 0 , " " } ,
{ " MAX_ROWS " , 0 , 0 , 0 , " " } ,
{ " MAX_UPDATES_PER_HOUR " , 0 , 0 , 0 , " " } ,
{ " MAX_USER_CONNECTIONS " , 0 , 0 , 0 , " " } ,
{ " MEDIUM " , 0 , 0 , 0 , " " } ,
{ " MEDIUMBLOB " , 0 , 0 , 0 , " " } ,
{ " MEDIUMINT " , 0 , 0 , 0 , " " } ,
{ " MEDIUMTEXT " , 0 , 0 , 0 , " " } ,
{ " MERGE " , 0 , 0 , 0 , " " } ,
{ " MICROSECOND " , 0 , 0 , 0 , " " } ,
{ " MIDDLEINT " , 0 , 0 , 0 , " " } ,
{ " MIGRATE " , 0 , 0 , 0 , " " } ,
{ " MINUTE " , 0 , 0 , 0 , " " } ,
{ " MINUTE_MICROSECOND " , 0 , 0 , 0 , " " } ,
{ " MINUTE_SECOND " , 0 , 0 , 0 , " " } ,
{ " MIN_ROWS " , 0 , 0 , 0 , " " } ,
{ " MOD " , 0 , 0 , 0 , " " } ,
{ " MODE " , 0 , 0 , 0 , " " } ,
{ " MODIFIES " , 0 , 0 , 0 , " " } ,
{ " MODIFY " , 0 , 0 , 0 , " " } ,
{ " MONTH " , 0 , 0 , 0 , " " } ,
{ " MULTILINESTRING " , 0 , 0 , 0 , " " } ,
{ " MULTIPOINT " , 0 , 0 , 0 , " " } ,
{ " MULTIPOLYGON " , 0 , 0 , 0 , " " } ,
{ " MUTEX " , 0 , 0 , 0 , " " } ,
{ " NAME " , 0 , 0 , 0 , " " } ,
{ " NAMES " , 0 , 0 , 0 , " " } ,
{ " NATIONAL " , 0 , 0 , 0 , " " } ,
{ " NATURAL " , 0 , 0 , 0 , " " } ,
{ " NDB " , 0 , 0 , 0 , " " } ,
{ " NDBCLUSTER " , 0 , 0 , 0 , " " } ,
{ " NCHAR " , 0 , 0 , 0 , " " } ,
{ " NEW " , 0 , 0 , 0 , " " } ,
{ " NEXT " , 0 , 0 , 0 , " " } ,
{ " NO " , 0 , 0 , 0 , " " } ,
{ " NONE " , 0 , 0 , 0 , " " } ,
{ " NOT " , 0 , 0 , 0 , " " } ,
{ " NO_WRITE_TO_BINLOG " , 0 , 0 , 0 , " " } ,
{ " NULL " , 0 , 0 , 0 , " " } ,
{ " NUMERIC " , 0 , 0 , 0 , " " } ,
{ " NVARCHAR " , 0 , 0 , 0 , " " } ,
{ " OFFSET " , 0 , 0 , 0 , " " } ,
{ " OLD_PASSWORD " , 0 , 0 , 0 , " " } ,
{ " ON " , 0 , 0 , 0 , " " } ,
{ " ONE " , 0 , 0 , 0 , " " } ,
{ " ONE_SHOT " , 0 , 0 , 0 , " " } ,
{ " OPEN " , 0 , 0 , 0 , " " } ,
{ " OPTIMIZE " , 0 , 0 , 0 , " " } ,
{ " OPTION " , 0 , 0 , 0 , " " } ,
{ " OPTIONALLY " , 0 , 0 , 0 , " " } ,
{ " OR " , 0 , 0 , 0 , " " } ,
{ " ORDER " , 0 , 0 , 0 , " " } ,
{ " OUT " , 0 , 0 , 0 , " " } ,
{ " OUTER " , 0 , 0 , 0 , " " } ,
{ " OUTFILE " , 0 , 0 , 0 , " " } ,
{ " PACK_KEYS " , 0 , 0 , 0 , " " } ,
{ " PARTIAL " , 0 , 0 , 0 , " " } ,
{ " PASSWORD " , 0 , 0 , 0 , " " } ,
{ " PHASE " , 0 , 0 , 0 , " " } ,
{ " POINT " , 0 , 0 , 0 , " " } ,
{ " POLYGON " , 0 , 0 , 0 , " " } ,
{ " PRECISION " , 0 , 0 , 0 , " " } ,
{ " PREPARE " , 0 , 0 , 0 , " " } ,
{ " PREV " , 0 , 0 , 0 , " " } ,
{ " PRIMARY " , 0 , 0 , 0 , " " } ,
{ " PRIVILEGES " , 0 , 0 , 0 , " " } ,
{ " PROCEDURE " , 0 , 0 , 0 , " " } ,
{ " PROCESS " , 0 , 0 , 0 , " " } ,
{ " PROCESSLIST " , 0 , 0 , 0 , " " } ,
{ " PURGE " , 0 , 0 , 0 , " " } ,
{ " QUARTER " , 0 , 0 , 0 , " " } ,
{ " QUERY " , 0 , 0 , 0 , " " } ,
{ " QUICK " , 0 , 0 , 0 , " " } ,
{ " RAID0 " , 0 , 0 , 0 , " " } ,
{ " RAID_CHUNKS " , 0 , 0 , 0 , " " } ,
{ " RAID_CHUNKSIZE " , 0 , 0 , 0 , " " } ,
{ " RAID_TYPE " , 0 , 0 , 0 , " " } ,
{ " READ " , 0 , 0 , 0 , " " } ,
{ " READS " , 0 , 0 , 0 , " " } ,
{ " REAL " , 0 , 0 , 0 , " " } ,
{ " RECOVER " , 0 , 0 , 0 , " " } ,
{ " REDUNDANT " , 0 , 0 , 0 , " " } ,
{ " REFERENCES " , 0 , 0 , 0 , " " } ,
{ " REGEXP " , 0 , 0 , 0 , " " } ,
{ " RELAY_LOG_FILE " , 0 , 0 , 0 , " " } ,
{ " RELAY_LOG_POS " , 0 , 0 , 0 , " " } ,
{ " RELAY_THREAD " , 0 , 0 , 0 , " " } ,
{ " RELEASE " , 0 , 0 , 0 , " " } ,
{ " RELOAD " , 0 , 0 , 0 , " " } ,
{ " RENAME " , 0 , 0 , 0 , " " } ,
{ " REPAIR " , 0 , 0 , 0 , " " } ,
{ " REPEATABLE " , 0 , 0 , 0 , " " } ,
{ " REPLACE " , 0 , 0 , 0 , " " } ,
{ " REPLICATION " , 0 , 0 , 0 , " " } ,
{ " REPEAT " , 0 , 0 , 0 , " " } ,
{ " REQUIRE " , 0 , 0 , 0 , " " } ,
{ " RESET " , 0 , 0 , 0 , " " } ,
{ " RESTORE " , 0 , 0 , 0 , " " } ,
{ " RESTRICT " , 0 , 0 , 0 , " " } ,
{ " RESUME " , 0 , 0 , 0 , " " } ,
{ " RETURN " , 0 , 0 , 0 , " " } ,
{ " RETURNS " , 0 , 0 , 0 , " " } ,
{ " REVOKE " , 0 , 0 , 0 , " " } ,
{ " RIGHT " , 0 , 0 , 0 , " " } ,
{ " RLIKE " , 0 , 0 , 0 , " " } ,
{ " ROLLBACK " , 0 , 0 , 0 , " " } ,
{ " ROLLUP " , 0 , 0 , 0 , " " } ,
{ " ROUTINE " , 0 , 0 , 0 , " " } ,
{ " ROW " , 0 , 0 , 0 , " " } ,
{ " ROWS " , 0 , 0 , 0 , " " } ,
{ " ROW_FORMAT " , 0 , 0 , 0 , " " } ,
{ " RTREE " , 0 , 0 , 0 , " " } ,
{ " SAVEPOINT " , 0 , 0 , 0 , " " } ,
{ " SCHEMA " , 0 , 0 , 0 , " " } ,
{ " SCHEMAS " , 0 , 0 , 0 , " " } ,
{ " SECOND " , 0 , 0 , 0 , " " } ,
{ " SECOND_MICROSECOND " , 0 , 0 , 0 , " " } ,
{ " SECURITY " , 0 , 0 , 0 , " " } ,
{ " SELECT " , 0 , 0 , 0 , " " } ,
{ " SENSITIVE " , 0 , 0 , 0 , " " } ,
{ " SEPARATOR " , 0 , 0 , 0 , " " } ,
{ " SERIAL " , 0 , 0 , 0 , " " } ,
{ " SERIALIZABLE " , 0 , 0 , 0 , " " } ,
{ " SESSION " , 0 , 0 , 0 , " " } ,
{ " SET " , 0 , 0 , 0 , " " } ,
{ " SHARE " , 0 , 0 , 0 , " " } ,
{ " SHOW " , 0 , 0 , 0 , " " } ,
{ " SHUTDOWN " , 0 , 0 , 0 , " " } ,
{ " SIGNED " , 0 , 0 , 0 , " " } ,
{ " SIMPLE " , 0 , 0 , 0 , " " } ,
{ " SLAVE " , 0 , 0 , 0 , " " } ,
{ " SNAPSHOT " , 0 , 0 , 0 , " " } ,
{ " SMALLINT " , 0 , 0 , 0 , " " } ,
{ " SOME " , 0 , 0 , 0 , " " } ,
{ " SONAME " , 0 , 0 , 0 , " " } ,
{ " SOUNDS " , 0 , 0 , 0 , " " } ,
{ " SPATIAL " , 0 , 0 , 0 , " " } ,
{ " SPECIFIC " , 0 , 0 , 0 , " " } ,
{ " SQL " , 0 , 0 , 0 , " " } ,
{ " SQLEXCEPTION " , 0 , 0 , 0 , " " } ,
{ " SQLSTATE " , 0 , 0 , 0 , " " } ,
{ " SQLWARNING " , 0 , 0 , 0 , " " } ,
{ " SQL_BIG_RESULT " , 0 , 0 , 0 , " " } ,
{ " SQL_BUFFER_RESULT " , 0 , 0 , 0 , " " } ,
{ " SQL_CACHE " , 0 , 0 , 0 , " " } ,
{ " SQL_CALC_FOUND_ROWS " , 0 , 0 , 0 , " " } ,
{ " SQL_NO_CACHE " , 0 , 0 , 0 , " " } ,
{ " SQL_SMALL_RESULT " , 0 , 0 , 0 , " " } ,
{ " SQL_THREAD " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_FRAC_SECOND " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_SECOND " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_MINUTE " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_HOUR " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_DAY " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_WEEK " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_MONTH " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_QUARTER " , 0 , 0 , 0 , " " } ,
{ " SQL_TSI_YEAR " , 0 , 0 , 0 , " " } ,
{ " SSL " , 0 , 0 , 0 , " " } ,
{ " START " , 0 , 0 , 0 , " " } ,
{ " STARTING " , 0 , 0 , 0 , " " } ,
{ " STATUS " , 0 , 0 , 0 , " " } ,
{ " STOP " , 0 , 0 , 0 , " " } ,
{ " STORAGE " , 0 , 0 , 0 , " " } ,
{ " STRAIGHT_JOIN " , 0 , 0 , 0 , " " } ,
{ " STRING " , 0 , 0 , 0 , " " } ,
{ " STRIPED " , 0 , 0 , 0 , " " } ,
{ " SUBJECT " , 0 , 0 , 0 , " " } ,
{ " SUPER " , 0 , 0 , 0 , " " } ,
{ " SUSPEND " , 0 , 0 , 0 , " " } ,
{ " TABLE " , 0 , 0 , 0 , " " } ,
{ " TABLES " , 0 , 0 , 0 , " " } ,
{ " TABLESPACE " , 0 , 0 , 0 , " " } ,
{ " TEMPORARY " , 0 , 0 , 0 , " " } ,
{ " TEMPTABLE " , 0 , 0 , 0 , " " } ,
{ " TERMINATED " , 0 , 0 , 0 , " " } ,
{ " TEXT " , 0 , 0 , 0 , " " } ,
{ " THEN " , 0 , 0 , 0 , " " } ,
{ " TIME " , 0 , 0 , 0 , " " } ,
{ " TIMESTAMP " , 0 , 0 , 0 , " " } ,
{ " TIMESTAMPADD " , 0 , 0 , 0 , " " } ,
{ " TIMESTAMPDIFF " , 0 , 0 , 0 , " " } ,
{ " TINYBLOB " , 0 , 0 , 0 , " " } ,
{ " TINYINT " , 0 , 0 , 0 , " " } ,
{ " TINYTEXT " , 0 , 0 , 0 , " " } ,
{ " TO " , 0 , 0 , 0 , " " } ,
{ " TRAILING " , 0 , 0 , 0 , " " } ,
{ " TRANSACTION " , 0 , 0 , 0 , " " } ,
{ " TRIGGER " , 0 , 0 , 0 , " " } ,
{ " TRIGGERS " , 0 , 0 , 0 , " " } ,
{ " TRUE " , 0 , 0 , 0 , " " } ,
{ " TRUNCATE " , 0 , 0 , 0 , " " } ,
{ " TYPE " , 0 , 0 , 0 , " " } ,
{ " TYPES " , 0 , 0 , 0 , " " } ,
{ " UNCOMMITTED " , 0 , 0 , 0 , " " } ,
{ " UNDEFINED " , 0 , 0 , 0 , " " } ,
{ " UNDO " , 0 , 0 , 0 , " " } ,
{ " UNICODE " , 0 , 0 , 0 , " " } ,
{ " UNION " , 0 , 0 , 0 , " " } ,
{ " UNIQUE " , 0 , 0 , 0 , " " } ,
{ " UNKNOWN " , 0 , 0 , 0 , " " } ,
{ " UNLOCK " , 0 , 0 , 0 , " " } ,
{ " UNSIGNED " , 0 , 0 , 0 , " " } ,
{ " UNTIL " , 0 , 0 , 0 , " " } ,
{ " UPDATE " , 0 , 0 , 0 , " " } ,
{ " UPGRADE " , 0 , 0 , 0 , " " } ,
{ " USAGE " , 0 , 0 , 0 , " " } ,
{ " USE " , 0 , 0 , 0 , " " } ,
{ " USER " , 0 , 0 , 0 , " " } ,
{ " USER_RESOURCES " , 0 , 0 , 0 , " " } ,
{ " USE_FRM " , 0 , 0 , 0 , " " } ,
{ " USING " , 0 , 0 , 0 , " " } ,
{ " UTC_DATE " , 0 , 0 , 0 , " " } ,
{ " UTC_TIME " , 0 , 0 , 0 , " " } ,
{ " UTC_TIMESTAMP " , 0 , 0 , 0 , " " } ,
{ " VALUE " , 0 , 0 , 0 , " " } ,
{ " VALUES " , 0 , 0 , 0 , " " } ,
{ " VARBINARY " , 0 , 0 , 0 , " " } ,
{ " VARCHAR " , 0 , 0 , 0 , " " } ,
{ " VARCHARACTER " , 0 , 0 , 0 , " " } ,
{ " VARIABLES " , 0 , 0 , 0 , " " } ,
{ " VARYING " , 0 , 0 , 0 , " " } ,
{ " WARNINGS " , 0 , 0 , 0 , " " } ,
{ " WEEK " , 0 , 0 , 0 , " " } ,
{ " WHEN " , 0 , 0 , 0 , " " } ,
{ " WHERE " , 0 , 0 , 0 , " " } ,
{ " WHILE " , 0 , 0 , 0 , " " } ,
{ " VIEW " , 0 , 0 , 0 , " " } ,
{ " WITH " , 0 , 0 , 0 , " " } ,
{ " WORK " , 0 , 0 , 0 , " " } ,
{ " WRITE " , 0 , 0 , 0 , " " } ,
{ " X509 " , 0 , 0 , 0 , " " } ,
{ " XOR " , 0 , 0 , 0 , " " } ,
{ " XA " , 0 , 0 , 0 , " " } ,
{ " YEAR " , 0 , 0 , 0 , " " } ,
{ " YEAR_MONTH " , 0 , 0 , 0 , " " } ,
{ " ZEROFILL " , 0 , 0 , 0 , " " } ,
{ " ABS " , 0 , 0 , 0 , " " } ,
{ " ACOS " , 0 , 0 , 0 , " " } ,
{ " ADDDATE " , 0 , 0 , 0 , " " } ,
{ " ADDTIME " , 0 , 0 , 0 , " " } ,
{ " AES_ENCRYPT " , 0 , 0 , 0 , " " } ,
{ " AES_DECRYPT " , 0 , 0 , 0 , " " } ,
{ " AREA " , 0 , 0 , 0 , " " } ,
{ " ASIN " , 0 , 0 , 0 , " " } ,
{ " ASBINARY " , 0 , 0 , 0 , " " } ,
{ " ASTEXT " , 0 , 0 , 0 , " " } ,
{ " ASWKB " , 0 , 0 , 0 , " " } ,
{ " ASWKT " , 0 , 0 , 0 , " " } ,
{ " ATAN " , 0 , 0 , 0 , " " } ,
{ " ATAN2 " , 0 , 0 , 0 , " " } ,
{ " BENCHMARK " , 0 , 0 , 0 , " " } ,
{ " BIN " , 0 , 0 , 0 , " " } ,
{ " BIT_COUNT " , 0 , 0 , 0 , " " } ,
{ " BIT_OR " , 0 , 0 , 0 , " " } ,
{ " BIT_AND " , 0 , 0 , 0 , " " } ,
{ " BIT_XOR " , 0 , 0 , 0 , " " } ,
{ " CAST " , 0 , 0 , 0 , " " } ,
{ " CEIL " , 0 , 0 , 0 , " " } ,
{ " CEILING " , 0 , 0 , 0 , " " } ,
{ " BIT_LENGTH " , 0 , 0 , 0 , " " } ,
{ " CENTROID " , 0 , 0 , 0 , " " } ,
{ " CHAR_LENGTH " , 0 , 0 , 0 , " " } ,
{ " CHARACTER_LENGTH " , 0 , 0 , 0 , " " } ,
{ " COALESCE " , 0 , 0 , 0 , " " } ,
{ " COERCIBILITY " , 0 , 0 , 0 , " " } ,
{ " COMPRESS " , 0 , 0 , 0 , " " } ,
{ " CONCAT " , 0 , 0 , 0 , " " } ,
{ " CONCAT_WS " , 0 , 0 , 0 , " " } ,
{ " CONNECTION_ID " , 0 , 0 , 0 , " " } ,
{ " CONV " , 0 , 0 , 0 , " " } ,
{ " CONVERT_TZ " , 0 , 0 , 0 , " " } ,
{ " COUNT " , 0 , 0 , 0 , " " } ,
{ " COS " , 0 , 0 , 0 , " " } ,
{ " COT " , 0 , 0 , 0 , " " } ,
{ " CRC32 " , 0 , 0 , 0 , " " } ,
{ " CROSSES " , 0 , 0 , 0 , " " } ,
{ " CURDATE " , 0 , 0 , 0 , " " } ,
{ " CURTIME " , 0 , 0 , 0 , " " } ,
{ " DATE_ADD " , 0 , 0 , 0 , " " } ,
{ " DATEDIFF " , 0 , 0 , 0 , " " } ,
{ " DATE_FORMAT " , 0 , 0 , 0 , " " } ,
{ " DATE_SUB " , 0 , 0 , 0 , " " } ,
{ " DAYNAME " , 0 , 0 , 0 , " " } ,
{ " DAYOFMONTH " , 0 , 0 , 0 , " " } ,
{ " DAYOFWEEK " , 0 , 0 , 0 , " " } ,
{ " DAYOFYEAR " , 0 , 0 , 0 , " " } ,
{ " DECODE " , 0 , 0 , 0 , " " } ,
{ " DEGREES " , 0 , 0 , 0 , " " } ,
{ " DES_ENCRYPT " , 0 , 0 , 0 , " " } ,
{ " DES_DECRYPT " , 0 , 0 , 0 , " " } ,
{ " DIMENSION " , 0 , 0 , 0 , " " } ,
{ " DISJOINT " , 0 , 0 , 0 , " " } ,
{ " ELT " , 0 , 0 , 0 , " " } ,
{ " ENCODE " , 0 , 0 , 0 , " " } ,
{ " ENCRYPT " , 0 , 0 , 0 , " " } ,
{ " ENDPOINT " , 0 , 0 , 0 , " " } ,
{ " ENVELOPE " , 0 , 0 , 0 , " " } ,
{ " EQUALS " , 0 , 0 , 0 , " " } ,
{ " EXTERIORRING " , 0 , 0 , 0 , " " } ,
{ " EXTRACT " , 0 , 0 , 0 , " " } ,
{ " EXP " , 0 , 0 , 0 , " " } ,
{ " EXPORT_SET " , 0 , 0 , 0 , " " } ,
{ " FIELD " , 0 , 0 , 0 , " " } ,
{ " FIND_IN_SET " , 0 , 0 , 0 , " " } ,
{ " FLOOR " , 0 , 0 , 0 , " " } ,
{ " FORMAT " , 0 , 0 , 0 , " " } ,
{ " FOUND_ROWS " , 0 , 0 , 0 , " " } ,
{ " FROM_DAYS " , 0 , 0 , 0 , " " } ,
{ " FROM_UNIXTIME " , 0 , 0 , 0 , " " } ,
{ " GET_LOCK " , 0 , 0 , 0 , " " } ,
{ " GEOMETRYN " , 0 , 0 , 0 , " " } ,
{ " GEOMETRYTYPE " , 0 , 0 , 0 , " " } ,
{ " GEOMCOLLFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " GEOMCOLLFROMWKB " , 0 , 0 , 0 , " " } ,
{ " GEOMETRYCOLLECTIONFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " GEOMETRYCOLLECTIONFROMWKB " , 0 , 0 , 0 , " " } ,
{ " GEOMETRYFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " GEOMETRYFROMWKB " , 0 , 0 , 0 , " " } ,
{ " GEOMFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " GEOMFROMWKB " , 0 , 0 , 0 , " " } ,
{ " GLENGTH " , 0 , 0 , 0 , " " } ,
{ " GREATEST " , 0 , 0 , 0 , " " } ,
{ " GROUP_CONCAT " , 0 , 0 , 0 , " " } ,
{ " GROUP_UNIQUE_USERS " , 0 , 0 , 0 , " " } ,
{ " HEX " , 0 , 0 , 0 , " " } ,
{ " IFNULL " , 0 , 0 , 0 , " " } ,
{ " INET_ATON " , 0 , 0 , 0 , " " } ,
{ " INET_NTOA " , 0 , 0 , 0 , " " } ,
{ " INSTR " , 0 , 0 , 0 , " " } ,
{ " INTERIORRINGN " , 0 , 0 , 0 , " " } ,
{ " INTERSECTS " , 0 , 0 , 0 , " " } ,
{ " ISCLOSED " , 0 , 0 , 0 , " " } ,
{ " ISEMPTY " , 0 , 0 , 0 , " " } ,
{ " ISNULL " , 0 , 0 , 0 , " " } ,
{ " IS_FREE_LOCK " , 0 , 0 , 0 , " " } ,
{ " IS_USED_LOCK " , 0 , 0 , 0 , " " } ,
{ " LAST_INSERT_ID " , 0 , 0 , 0 , " " } ,
{ " ISSIMPLE " , 0 , 0 , 0 , " " } ,
{ " LAST_DAY " , 0 , 0 , 0 , " " } ,
{ " LCASE " , 0 , 0 , 0 , " " } ,
{ " LEAST " , 0 , 0 , 0 , " " } ,
{ " LENGTH " , 0 , 0 , 0 , " " } ,
{ " LN " , 0 , 0 , 0 , " " } ,
{ " LINEFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " LINEFROMWKB " , 0 , 0 , 0 , " " } ,
{ " LINESTRINGFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " LINESTRINGFROMWKB " , 0 , 0 , 0 , " " } ,
{ " LOAD_FILE " , 0 , 0 , 0 , " " } ,
{ " LOCATE " , 0 , 0 , 0 , " " } ,
{ " LOG " , 0 , 0 , 0 , " " } ,
{ " LOG2 " , 0 , 0 , 0 , " " } ,
{ " LOG10 " , 0 , 0 , 0 , " " } ,
{ " LOWER " , 0 , 0 , 0 , " " } ,
{ " LPAD " , 0 , 0 , 0 , " " } ,
{ " LTRIM " , 0 , 0 , 0 , " " } ,
{ " MAKE_SET " , 0 , 0 , 0 , " " } ,
{ " MAKEDATE " , 0 , 0 , 0 , " " } ,
{ " MAKETIME " , 0 , 0 , 0 , " " } ,
{ " MASTER_POS_WAIT " , 0 , 0 , 0 , " " } ,
{ " MAX " , 0 , 0 , 0 , " " } ,
{ " MBRCONTAINS " , 0 , 0 , 0 , " " } ,
{ " MBRDISJOINT " , 0 , 0 , 0 , " " } ,
{ " MBREQUAL " , 0 , 0 , 0 , " " } ,
{ " MBRINTERSECTS " , 0 , 0 , 0 , " " } ,
{ " MBROVERLAPS " , 0 , 0 , 0 , " " } ,
{ " MBRTOUCHES " , 0 , 0 , 0 , " " } ,
{ " MBRWITHIN " , 0 , 0 , 0 , " " } ,
{ " MD5 " , 0 , 0 , 0 , " " } ,
{ " MID " , 0 , 0 , 0 , " " } ,
{ " MIN " , 0 , 0 , 0 , " " } ,
{ " MLINEFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " MLINEFROMWKB " , 0 , 0 , 0 , " " } ,
{ " MPOINTFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " MPOINTFROMWKB " , 0 , 0 , 0 , " " } ,
{ " MPOLYFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " MPOLYFROMWKB " , 0 , 0 , 0 , " " } ,
{ " MONTHNAME " , 0 , 0 , 0 , " " } ,
{ " MULTILINESTRINGFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " MULTILINESTRINGFROMWKB " , 0 , 0 , 0 , " " } ,
{ " MULTIPOINTFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " MULTIPOINTFROMWKB " , 0 , 0 , 0 , " " } ,
{ " MULTIPOLYGONFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " MULTIPOLYGONFROMWKB " , 0 , 0 , 0 , " " } ,
{ " NAME_CONST " , 0 , 0 , 0 , " " } ,
{ " NOW " , 0 , 0 , 0 , " " } ,
{ " NULLIF " , 0 , 0 , 0 , " " } ,
{ " NUMGEOMETRIES " , 0 , 0 , 0 , " " } ,
{ " NUMINTERIORRINGS " , 0 , 0 , 0 , " " } ,
{ " NUMPOINTS " , 0 , 0 , 0 , " " } ,
{ " OCTET_LENGTH " , 0 , 0 , 0 , " " } ,
{ " OCT " , 0 , 0 , 0 , " " } ,
{ " ORD " , 0 , 0 , 0 , " " } ,
{ " OVERLAPS " , 0 , 0 , 0 , " " } ,
{ " PERIOD_ADD " , 0 , 0 , 0 , " " } ,
{ " PERIOD_DIFF " , 0 , 0 , 0 , " " } ,
{ " PI " , 0 , 0 , 0 , " " } ,
{ " POINTFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " POINTFROMWKB " , 0 , 0 , 0 , " " } ,
{ " POINTN " , 0 , 0 , 0 , " " } ,
{ " POLYFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " POLYFROMWKB " , 0 , 0 , 0 , " " } ,
{ " POLYGONFROMTEXT " , 0 , 0 , 0 , " " } ,
{ " POLYGONFROMWKB " , 0 , 0 , 0 , " " } ,
{ " POSITION " , 0 , 0 , 0 , " " } ,
{ " POW " , 0 , 0 , 0 , " " } ,
{ " POWER " , 0 , 0 , 0 , " " } ,
{ " QUOTE " , 0 , 0 , 0 , " " } ,
{ " RADIANS " , 0 , 0 , 0 , " " } ,
{ " RAND " , 0 , 0 , 0 , " " } ,
{ " RELEASE_LOCK " , 0 , 0 , 0 , " " } ,
{ " REVERSE " , 0 , 0 , 0 , " " } ,
{ " ROUND " , 0 , 0 , 0 , " " } ,
{ " ROW_COUNT " , 0 , 0 , 0 , " " } ,
{ " RPAD " , 0 , 0 , 0 , " " } ,
{ " RTRIM " , 0 , 0 , 0 , " " } ,
{ " SEC_TO_TIME " , 0 , 0 , 0 , " " } ,
{ " SESSION_USER " , 0 , 0 , 0 , " " } ,
{ " SUBDATE " , 0 , 0 , 0 , " " } ,
{ " SIGN " , 0 , 0 , 0 , " " } ,
{ " SIN " , 0 , 0 , 0 , " " } ,
{ " SHA " , 0 , 0 , 0 , " " } ,
{ " SHA1 " , 0 , 0 , 0 , " " } ,
{ " SLEEP " , 0 , 0 , 0 , " " } ,
{ " SOUNDEX " , 0 , 0 , 0 , " " } ,
{ " SPACE " , 0 , 0 , 0 , " " } ,
{ " SQRT " , 0 , 0 , 0 , " " } ,
{ " SRID " , 0 , 0 , 0 , " " } ,
{ " STARTPOINT " , 0 , 0 , 0 , " " } ,
{ " STD " , 0 , 0 , 0 , " " } ,
{ " STDDEV " , 0 , 0 , 0 , " " } ,
{ " STDDEV_POP " , 0 , 0 , 0 , " " } ,
{ " STDDEV_SAMP " , 0 , 0 , 0 , " " } ,
{ " STR_TO_DATE " , 0 , 0 , 0 , " " } ,
{ " STRCMP " , 0 , 0 , 0 , " " } ,
{ " SUBSTR " , 0 , 0 , 0 , " " } ,
{ " SUBSTRING " , 0 , 0 , 0 , " " } ,
{ " SUBSTRING_INDEX " , 0 , 0 , 0 , " " } ,
{ " SUBTIME " , 0 , 0 , 0 , " " } ,
{ " SUM " , 0 , 0 , 0 , " " } ,
{ " SYSDATE " , 0 , 0 , 0 , " " } ,
{ " SYSTEM_USER " , 0 , 0 , 0 , " " } ,
{ " TAN " , 0 , 0 , 0 , " " } ,
{ " TIME_FORMAT " , 0 , 0 , 0 , " " } ,
{ " TIME_TO_SEC " , 0 , 0 , 0 , " " } ,
{ " TIMEDIFF " , 0 , 0 , 0 , " " } ,
{ " TO_DAYS " , 0 , 0 , 0 , " " } ,
{ " TOUCHES " , 0 , 0 , 0 , " " } ,
{ " TRIM " , 0 , 0 , 0 , " " } ,
{ " UCASE " , 0 , 0 , 0 , " " } ,
{ " UNCOMPRESS " , 0 , 0 , 0 , " " } ,
{ " UNCOMPRESSED_LENGTH " , 0 , 0 , 0 , " " } ,
{ " UNHEX " , 0 , 0 , 0 , " " } ,
{ " UNIQUE_USERS " , 0 , 0 , 0 , " " } ,
{ " UNIX_TIMESTAMP " , 0 , 0 , 0 , " " } ,
{ " UPPER " , 0 , 0 , 0 , " " } ,
{ " UUID " , 0 , 0 , 0 , " " } ,
{ " VARIANCE " , 0 , 0 , 0 , " " } ,
{ " VAR_POP " , 0 , 0 , 0 , " " } ,
{ " VAR_SAMP " , 0 , 0 , 0 , " " } ,
{ " VERSION " , 0 , 0 , 0 , " " } ,
{ " WEEKDAY " , 0 , 0 , 0 , " " } ,
{ " WEEKOFYEAR " , 0 , 0 , 0 , " " } ,
{ " WITHIN " , 0 , 0 , 0 , " " } ,
{ " X " , 0 , 0 , 0 , " " } ,
{ " Y " , 0 , 0 , 0 , " " } ,
{ " YEARWEEK " , 0 , 0 , 0 , " " } ,
/* end sentinel */
2000-08-11 17:17:38 +02:00
{ ( 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
2004-03-03 21:54:37 +01:00
/*
HIST_ENTRY is defined for libedit , but not for the real readline
Need to redefine it for real readline to find it
*/
2004-08-24 16:23:23 +02:00
# if !defined(HAVE_HIST_ENTRY)
2004-03-03 21:54:37 +01:00
typedef struct _hist_entry {
const char * line ;
const char * data ;
} HIST_ENTRY ;
# endif
2003-01-18 17:28:48 +01:00
extern " C " int add_history ( const char * command ) ; /* From readline directory */
extern " C " int read_history ( const char * command ) ;
extern " C " int write_history ( const char * command ) ;
2004-03-03 21:54:37 +01:00
extern " C " HIST_ENTRY * history_get ( int num ) ;
extern " C " int history_length ;
static int not_in_history ( const char * line ) ;
2000-07-31 21:29:14 +02:00
static void initialize_readline ( char * name ) ;
2004-03-03 21:54:37 +01:00
static void fix_history ( String * final_command ) ;
2000-07-31 21:29:14 +02:00
# endif
2005-10-06 16:54:43 +02:00
static COMMANDS * find_command ( char * name , char cmd_name ) ;
2002-12-23 23:53:07 +01:00
static bool add_line ( String & buffer , char * line , char * in_string ,
2009-03-18 09:18:24 +01:00
bool * ml_comment , bool truncated ) ;
2000-07-31 21:29:14 +02:00
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 ) ;
2005-04-05 15:30:17 +02:00
static void print_warnings ( void ) ;
2000-07-31 21:29:14 +02:00
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 ) ;
2006-08-10 03:46:46 +02:00
static sig_handler mysql_sigint ( int sig ) ;
2000-07-31 21:29:14 +02:00
int main ( int argc , char * argv [ ] )
{
char buff [ 80 ] ;
2005-07-18 14:33:18 +02:00
char * defaults , * extra_defaults , * group_suffix ;
char * emb_argv [ 4 ] ;
int emb_argc ;
2005-01-03 16:21:54 +01:00
2005-07-18 14:33:18 +02:00
/* Get --defaults-xxx args for mysql_server_init() */
emb_argc = get_defaults_options ( argc , argv , & defaults , & extra_defaults ,
& group_suffix ) + 1 ;
memcpy ( ( char * ) emb_argv , ( char * ) argv , emb_argc * sizeof ( * argv ) ) ;
emb_argv [ emb_argc ] = 0 ;
2000-07-31 21:29:14 +02:00
MY_INIT ( argv [ 0 ] ) ;
DBUG_ENTER ( " main " ) ;
DBUG_PROCESS ( argv [ 0 ] ) ;
2003-04-23 02:29:03 +02:00
delimiter_str = delimiter ;
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 ;
2003-01-28 07:38:28 +01:00
outfile [ 0 ] = 0 ; // no (default) outfile
strmov ( pager , " stdout " ) ; // the default, if --pager wasn't given
2001-04-17 00:45:30 +02:00
{
char * tmp = getenv ( " PAGER " ) ;
2004-01-14 03:58:37 +01:00
if ( tmp & & strlen ( tmp ) )
{
default_pager_set = 1 ;
strmov ( default_pager , tmp ) ;
}
2001-04-17 00:45:30 +02:00
}
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 ;
2006-10-10 00:28:06 +02:00
{
/*
The file descriptor - layer may be out - of - sync with the file - number layer ,
so we make sure that " stdout " is really open . If its file is closed then
explicitly close the FD layer .
*/
int stdout_fileno_copy ;
stdout_fileno_copy = dup ( fileno ( stdout ) ) ; /* Okay if fileno fails. */
if ( stdout_fileno_copy = = - 1 )
fclose ( stdout ) ;
else
close ( stdout_fileno_copy ) ; /* Clean up dup(). */
}
2000-07-31 21:29:14 +02:00
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 & &
2009-03-18 09:18:24 +01:00
! ( status . line_buff = batch_readline_init ( MAX_BATCH_BUFFER_SIZE , stdin ) ) )
2002-08-24 01:08:10 +02:00
{
free_defaults ( defaults_argv ) ;
2004-05-21 14:23:27 +02:00
my_end ( 0 ) ;
2000-07-31 21:29:14 +02:00
exit ( 1 ) ;
2002-08-24 01:08:10 +02:00
}
2005-01-03 16:21:54 +01:00
if ( mysql_server_init ( emb_argc , emb_argv , ( char * * ) server_default_groups ) )
2004-05-17 09:07:58 +02:00
{
2008-02-27 09:42:43 +01:00
put_error ( NULL ) ;
2004-05-17 09:07:58 +02:00
free_defaults ( defaults_argv ) ;
2004-05-21 14:23:27 +02:00
my_end ( 0 ) ;
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
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
2004-10-07 21:47:11 +02:00
if ( opt_sigint_ignore )
signal ( SIGINT , SIG_IGN ) ;
else
2006-08-10 03:46:46 +02:00
signal ( SIGINT , mysql_sigint ) ; // 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
put_info ( " Welcome to the MySQL monitor. Commands end with ; or \\ g. " ,
INFO_INFO ) ;
sprintf ( ( char * ) glob_buffer . ptr ( ) ,
2006-09-29 20:52:48 +02:00
" Your MySQL connection id is %lu \n Server version: %s \n " ,
mysql_thread_id ( & mysql ) , server_version_string ( & mysql ) ) ;
2000-07-31 21:29:14 +02:00
put_info ( ( char * ) glob_buffer . ptr ( ) , INFO_INFO ) ;
# ifdef HAVE_READLINE
2005-07-31 11:49:55 +02:00
initialize_readline ( ( char * ) 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 " ) ) ;
2006-05-09 11:01:50 +02:00
char link_name [ FN_REFLEN ] ;
if ( my_readlink ( link_name , histfile , 0 ) = = 0 & &
strncmp ( link_name , " /dev/null " , 10 ) = = 0 )
{
/* The .mysql_history file is a symlink to /dev/null, don't use it */
my_free ( histfile , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
histfile = 0 ;
}
2000-07-31 21:29:14 +02:00
}
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 ) ;
2005-01-25 17:32:09 +01:00
if ( ! ( histfile_tmp = ( char * ) my_malloc ( ( uint ) strlen ( histfile ) + 5 ,
MYF ( MY_WME ) ) ) )
{
fprintf ( stderr , " Couldn't allocate memory for temp histfile! \n " ) ;
exit ( 1 ) ;
}
sprintf ( histfile_tmp , " %s.TMP " , histfile ) ;
2000-07-31 21:29:14 +02:00
}
}
# endif
2003-01-06 00:48:59 +01:00
sprintf ( buff , " %s " ,
2004-04-05 15:28:16 +02:00
# ifndef NOT_YET
2009-03-19 09:37:34 +01:00
" Type 'help;' or ' \\ h' for help. Type ' \\ c' to clear the current input statement. \n " ) ;
2004-04-05 15:28:16 +02:00
# else
2002-10-28 14:44:19 +01:00
" Type 'help [[%]function name[%]]' to get help on usage of function. \n " ) ;
2003-01-06 00:48:59 +01:00
# endif
2000-07-31 21:29:14 +02:00
put_info ( buff , INFO_INFO ) ;
2005-08-09 21:17:28 +02:00
status . exit_status = read_and_execute ( ! status . batch ) ;
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
}
2006-08-10 03:46:46 +02:00
sig_handler mysql_sigint ( int sig )
{
char kill_buffer [ 40 ] ;
MYSQL * kill_mysql = NULL ;
/* terminate if no query being executed, or we already tried interrupting */
if ( ! executing_query | | interrupted_query + + )
2008-03-28 19:02:27 +01:00
goto err ;
2006-08-10 03:46:46 +02:00
kill_mysql = mysql_init ( kill_mysql ) ;
if ( ! mysql_real_connect ( kill_mysql , current_host , current_user , opt_password ,
" " , opt_mysql_port , opt_mysql_unix_port , 0 ) )
2008-03-28 19:02:27 +01:00
goto err ;
2006-08-10 03:46:46 +02:00
/* kill_buffer is always big enough because max length of %lu is 15 */
sprintf ( kill_buffer , " KILL /*!50000 QUERY */ %lu " , mysql_thread_id ( & mysql ) ) ;
2009-02-10 23:47:54 +01:00
mysql_real_query ( kill_mysql , kill_buffer , ( uint ) strlen ( kill_buffer ) ) ;
2006-08-10 03:46:46 +02:00
mysql_close ( kill_mysql ) ;
tee_fprintf ( stdout , " Query aborted by Ctrl+C \n " ) ;
2008-03-28 19:02:27 +01:00
return ;
err :
# ifdef _WIN32
/*
When SIGINT is raised on Windows , the OS creates a new thread to handle the
interrupt . Once that thread completes , the main thread continues running
only to find that it ' s resources have already been free ' d when the sigint
handler called mysql_end ( ) .
*/
mysql_thread_end ( ) ;
return ;
# else
mysql_end ( sig ) ;
# endif
2006-08-10 03:46:46 +02:00
}
2000-07-31 21:29:14 +02:00
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
2006-05-09 11:01:50 +02:00
if ( ! status . batch & & ! quick & & ! opt_html & & ! opt_xml & & histfile )
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 ) ;
2005-01-25 17:32:09 +01:00
if ( ! write_history ( histfile_tmp ) )
my_rename ( histfile_tmp , histfile , MYF ( MY_WME ) ) ;
2000-07-31 21:29:14 +02:00
}
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 ) ) ;
2005-01-25 17:32:09 +01:00
my_free ( histfile_tmp , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
2000-07-31 21:29:14 +02:00
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 ) ;
2008-03-28 19:02:27 +01:00
my_end ( info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR ) ;
2000-07-31 21:29:14 +02:00
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 } ,
2004-01-14 03:58:37 +01:00
{ " help " , ' I ' , " Synonym for -? " , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 ,
0 , 0 , 0 , 0 , 0 } ,
2005-08-24 21:03:34 +02:00
# ifdef __NETWARE__
2005-11-18 18:25:46 +01:00
{ " autoclose " , OPT_AUTO_CLOSE , " Auto close the screen on exit for Netware. " ,
2005-08-24 21:03:34 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
2002-04-02 19:29:53 +02:00
{ " 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. " ,
2006-12-14 23:51:37 +01:00
( gptr * ) & opt_rehash , ( gptr * ) & opt_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 ' ,
2004-05-05 22:47:09 +02:00
" Don't use history file. Disable interactive behavior. (Enables --silent) " , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " 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 } ,
2007-11-19 13:27:44 +01:00
{ " comments " , ' c ' , " Preserve comments. Send comments to the server. "
" The default is --skip-comments (discard comments), enable with --comments " ,
( gptr * ) & preserve_comments , ( gptr * ) & preserve_comments ,
0 , GET_BOOL , NO_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 } ,
2004-01-14 03:58:37 +01:00
# ifdef DBUG_OFF
{ " debug " , ' # ' , " This is a non-debug version. Catch this and exit " ,
2004-01-14 16:42:08 +01:00
0 , 0 , 0 , GET_DISABLED , OPT_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2004-01-14 03:58:37 +01:00
# else
{ " debug " , ' # ' , " Output debug log " , ( gptr * ) & default_dbug_option ,
2002-04-02 19:29:53 +02:00
( 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 } ,
2003-04-23 02:29:03 +02:00
{ " delimiter " , OPT_DELIMITER , " Delimiter to be used. " , ( gptr * ) & delimiter_str ,
( gptr * ) & delimiter_str , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2004-05-05 22:47:09 +02:00
{ " execute " , ' e ' , " Execute command and quit. (Disables --force and history file) " , 0 ,
2002-04-02 19:29:53 +02:00
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 } ,
{ " 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 } ,
2006-07-13 09:31:47 +02:00
{ " no-named-commands " , ' g ' ,
" 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. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2009-05-07 19:28:29 +02:00
{ " ignore-spaces " , ' i ' , " Ignore space after function names. " ,
( gptr * ) & ignore_spaces , ( gptr * ) & ignore_spaces , 0 , GET_BOOL , 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 } ,
{ " 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 } ,
2004-10-07 21:47:11 +02:00
{ " sigint-ignore " , OPT_SIGINT_IGNORE , " Ignore SIGINT (CTRL-C) " ,
( gptr * ) & opt_sigint_ignore , ( gptr * ) & opt_sigint_ignore , 0 , GET_BOOL ,
NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " 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 } ,
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
2002-04-02 19:29:53 +02:00
{ " pager " , OPT_PAGER ,
2006-07-13 09:31:47 +02:00
" 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. Disable with --disable-pager. This option is disabled by default. " ,
2002-04-02 19:29:53 +02:00
0 , 0 , 0 , GET_STR , OPT_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2006-07-13 09:31:47 +02:00
{ " no-pager " , OPT_NOPAGER ,
" Disable pager and print to stdout. See interactive help ( \\ h) also. WARNING: option deprecated; use --disable-pager instead. " ,
0 , 0 , 0 , GET_NO_ARG , NO_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
2007-09-13 16:19:46 +02:00
{ " port " , ' P ' , " Port number to use for connection or 0 for default to, in "
" order of preference, my.cnf, $MYSQL_TCP_PORT, "
# if MYSQL_PORT_DEFAULT == 0
" /etc/services, "
# endif
" built-in default ( " STRINGIFY_ARG ( MYSQL_PORT ) " ). " ,
( gptr * ) & opt_mysql_port ,
( gptr * ) & opt_mysql_port , 0 , GET_UINT , REQUIRED_ARG , 0 , 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 } ,
2003-06-13 10:59:02 +02:00
{ " protocol " , OPT_MYSQL_PROTOCOL , " The protocol of connection (tcp,socket,pipe,memory). " ,
2002-11-14 20:16:30 +01:00
0 , 0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ " quick " , ' q ' ,
2003-06-13 10:59:02 +02:00
" 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. " ,
2002-04-02 19:29:53 +02:00
( gptr * ) & quick , ( gptr * ) & quick , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2003-06-13 10:59:02 +02:00
{ " raw " , ' r ' , " Write fields without conversion. Used with --batch. " ,
2002-04-02 19:29:53 +02:00
( gptr * ) & opt_raw_data , ( gptr * ) & opt_raw_data , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 ,
0 , 0 , 0 } ,
2003-03-01 23:34:34 +01:00
{ " reconnect " , OPT_RECONNECT , " Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default. " ,
( gptr * ) & opt_reconnect , ( gptr * ) & opt_reconnect , 0 , GET_BOOL , NO_ARG , 1 , 0 , 0 , 0 , 0 , 0 } ,
2004-05-05 22:47:09 +02:00
{ " silent " , ' s ' , " Be more silent. Print results with a tab as separator, each row on new line. " , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 ,
2002-04-02 19:29:53 +02:00
0 , 0 } ,
2002-11-14 20:16:30 +01:00
# ifdef HAVE_SMEM
2004-08-30 18:11:10 +02:00
{ " shared-memory-base-name " , OPT_SHARED_MEMORY_BASE_NAME ,
2003-06-13 10:59:02 +02:00
" Base name of shared memory. " , ( gptr * ) & shared_memory_base_name , ( gptr * ) & shared_memory_base_name ,
2002-11-14 20:16:30 +01:00
0 , GET_STR_ALLOC , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
2006-04-18 10:16:06 +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 ,
2006-07-13 09:31:47 +02:00
" Append everything into outfile. See interactive help ( \\ h) also. Does not work in batch mode. Disable with --disable-tee. This option is disabled by default. " ,
2002-04-02 19:29:53 +02:00
0 , 0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2006-07-13 09:31:47 +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 ,
NO_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. " ,
2004-03-15 16:47:51 +01:00
( gptr * ) & safe_updates , ( gptr * ) & safe_updates , 0 , GET_BOOL , NO_ARG , 0 , 0 ,
2002-04-02 19:29:53 +02:00
0 , 0 , 0 , 0 } ,
2002-10-04 16:18:41 +02:00
{ " i-am-a-dummy " , ' U ' , " Synonym for option --safe-updates, -U. " ,
2004-03-15 16:47:51 +01:00
( gptr * ) & safe_updates , ( gptr * ) & safe_updates , 0 , GET_BOOL , NO_ARG , 0 , 0 ,
2002-10-04 16:18:41 +02:00
0 , 0 , 0 , 0 } ,
2003-06-13 10:59:02 +02:00
{ " verbose " , ' v ' , " Write more. (-v -v -v gives the table output format). " , 0 ,
2002-04-02 19:29:53 +02:00
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 } ,
2004-01-14 03:58:37 +01:00
{ " connect_timeout " , OPT_CONNECT_TIMEOUT ,
" Number of seconds before connection 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 } ,
2004-01-14 03:58:37 +01:00
{ " max_allowed_packet " , OPT_MAX_ALLOWED_PACKET ,
" Max packet length to send to, or receive from server " ,
2007-11-30 06:32:04 +01:00
( gptr * ) & opt_max_allowed_packet , ( gptr * ) & opt_max_allowed_packet , 0 ,
GET_ULONG , REQUIRED_ARG , 16 * 1024L * 1024L , 4096 ,
( longlong ) 2 * 1024L * 1024L * 1024L , MALLOC_OVERHEAD , 1024 , 0 } ,
2004-01-14 03:58:37 +01:00
{ " net_buffer_length " , OPT_NET_BUFFER_LENGTH ,
" Buffer for TCP/IP and socket communication " ,
2004-05-26 18:40:27 +02:00
( gptr * ) & opt_net_buffer_length , ( gptr * ) & opt_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 } ,
2004-01-14 03:58:37 +01:00
{ " select_limit " , OPT_SELECT_LIMIT ,
" Automatic limit for SELECT when using --safe-updates " ,
( gptr * ) & select_limit ,
2007-11-30 06:32:04 +01:00
( gptr * ) & select_limit , 0 , GET_ULONG , REQUIRED_ARG , 1000L , 1 , ULONG_MAX ,
0 , 1 , 0 } ,
2004-01-14 03:58:37 +01:00
{ " max_join_size " , OPT_MAX_JOIN_SIZE ,
" Automatic limit for rows in a join when using --safe-updates " ,
( gptr * ) & max_join_size ,
2007-11-30 06:32:04 +01:00
( gptr * ) & max_join_size , 0 , GET_ULONG , REQUIRED_ARG , 1000000L , 1 , ULONG_MAX ,
0 , 1 , 0 } ,
2003-11-28 11:11:44 +01:00
{ " secure-auth " , OPT_SECURE_AUTH , " Refuse client connecting to server if it "
" uses old (pre-4.1.1) protocol " , ( gptr * ) & opt_secure_auth ,
( gptr * ) & opt_secure_auth , 0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2005-04-05 15:30:17 +02:00
{ " show-warnings " , OPT_SHOW_WARNINGS , " Show warnings after every statement. " ,
( gptr * ) & show_warnings , ( gptr * ) & show_warnings , 0 , GET_BOOL , NO_ARG ,
0 , 0 , 0 , 0 , 0 , 0 } ,
2002-04-02 19:29:53 +02:00
{ 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 )
{
2004-05-25 21:00:14 +02:00
/* Divert all help information on NetWare to logger screen. */
# ifdef __NETWARE__
# define printf consoleprintf
# endif
2005-04-25 12:05:13 +02:00
# if defined(USE_LIBEDIT_INTERFACE)
const char * readline = " " ;
# else
const char * readline = " readline " ;
# endif
2005-05-05 17:48:50 +02:00
# ifdef HAVE_READLINE
2005-04-25 12:05:13 +02:00
printf ( " %s Ver %s Distrib %s, for %s (%s) using %s %s \n " ,
my_progname , VER , MYSQL_SERVER_VERSION , SYSTEM_TYPE , MACHINE_TYPE ,
readline , rl_library_version ) ;
2005-05-05 17:48:50 +02:00
# else
2005-12-05 12:12:08 +01:00
printf ( " %s Ver %s Distrib %s, for %s (%s) \n " , my_progname , VER ,
2005-05-05 17:48:50 +02:00
MYSQL_SERVER_VERSION , SYSTEM_TYPE , MACHINE_TYPE ) ;
# endif
2000-07-31 21:29:14 +02:00
if ( version )
return ;
2002-04-03 12:36:01 +02:00
printf ( " \
2008-01-25 16:53:21 +01:00
Copyright ( C ) 2000 - 2008 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 ) ;
2004-05-25 21:00:14 +02:00
NETWARE_SET_SCREEN_MODE ( 1 ) ;
# ifdef __NETWARE__
# undef printf
# endif
2000-07-31 21:29:14 +02:00
}
2004-05-25 21:00: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 ) {
2005-08-24 21:03:34 +02:00
# ifdef __NETWARE__
case OPT_AUTO_CLOSE :
setscreenmode ( SCR_AUTOCLOSE_ON_EXIT ) ;
break ;
# endif
2002-05-31 14:43:21 +02:00
case OPT_CHARSETS_DIR :
2007-04-16 09:28:02 +02:00
strmake ( mysql_charsets_dir , argument , sizeof ( mysql_charsets_dir ) - 1 ) ;
2002-05-31 14:43:21 +02:00
charsets_dir = mysql_charsets_dir ;
break ;
2003-08-18 23:08:08 +02:00
case OPT_DEFAULT_CHARSET :
default_charset_used = 1 ;
break ;
2003-04-23 02:29:03 +02:00
case OPT_DELIMITER :
2006-10-02 17:45:48 +02:00
if ( argument = = disabled_my_option )
{
2003-04-23 02:29:03 +02:00
strmov ( delimiter , DEFAULT_DELIMITER ) ;
2006-10-02 17:45:48 +02:00
}
else
{
/* Check that delimiter does not contain a backslash */
if ( ! strstr ( argument , " \\ " ) )
{
strmake ( delimiter , argument , sizeof ( delimiter ) - 1 ) ;
}
else
{
put_info ( " DELIMITER cannot contain a backslash character " , INFO_ERROR ) ;
return 0 ;
}
}
2005-03-07 09:47:24 +01:00
delimiter_length = ( uint ) strlen ( delimiter ) ;
2003-04-23 02:29:03 +02:00
delimiter_str = delimiter ;
break ;
2002-05-31 14:43:21 +02:00
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
2003-01-28 07:38:28 +01:00
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 ;
2004-01-14 03:58:37 +01:00
if ( argument & & strlen ( argument ) )
{
default_pager_set = 1 ;
2007-04-16 09:28:02 +02:00
strmake ( pager , argument , sizeof ( pager ) - 1 ) ;
2004-01-14 03:58:37 +01:00
strmov ( default_pager , pager ) ;
}
else if ( default_pager_set )
2002-10-15 22:34:55 +02:00
strmov ( pager , default_pager ) ;
2004-01-14 03:58:37 +01:00
else
opt_nopager = 1 ;
2002-10-15 22:34:55 +02:00
}
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 ;
2006-06-02 21:03:39 +02:00
break ;
2002-11-14 20:16:30 +01:00
case OPT_MYSQL_PROTOCOL :
{
2004-08-24 17:13:31 +02:00
if ( ( opt_protocol = find_type ( argument , & sql_protocol_typelib , 0 ) ) < = 0 )
2002-11-14 20:16:30 +01:00
{
fprintf ( stderr , " Unknown option to protocol: %s \n " , argument ) ;
exit ( 1 ) ;
}
break ;
}
2003-12-01 12:13:16 +01:00
break ;
2002-05-31 14:43:21 +02:00
case ' A ' :
2006-12-14 23:51:37 +01:00
opt_rehash = 0 ;
2002-05-31 14:43:21 +02:00
break ;
case ' N ' :
column_names = 0 ;
break ;
case ' e ' :
status . batch = 1 ;
status . add_to_history = 0 ;
2004-05-05 22:47:09 +02:00
if ( ! status . line_buff )
ignore_errors = 0 ; // do it for the first -e only
if ( ! ( status . line_buff = batch_readline_command ( status . line_buff , argument ) ) )
2002-05-31 14:43:21 +02:00
return 1 ;
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 ;
2004-08-26 15:15:36 +02:00
tty_password = 0 ;
2002-05-31 14:43:21 +02:00
}
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 ' :
2004-05-05 22:47:09 +02:00
status . batch = 1 ;
status . add_to_history = 0 ;
2004-05-06 15:13:23 +02:00
set_if_bigger ( opt_silent , 1 ) ; // more silent
2002-05-31 14:43:21 +02:00
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 ;
2004-05-26 18:40:27 +02:00
MYSQL_PARAMETERS * mysql_params = mysql_get_parameters ( ) ;
2002-04-02 19:29:53 +02:00
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 ) ;
2004-05-26 18:40:27 +02:00
opt_max_allowed_packet = * mysql_params - > p_max_allowed_packet ;
opt_net_buffer_length = * mysql_params - > p_net_buffer_length ;
2004-08-31 18:27:58 +02:00
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
2004-05-26 18:40:27 +02:00
* mysql_params - > p_max_allowed_packet = opt_max_allowed_packet ;
* mysql_params - > p_net_buffer_length = opt_net_buffer_length ;
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 ;
2004-01-14 03:58:37 +01:00
default_pager_set = 0 ;
2002-04-02 19:29:53 +02:00
opt_outfile = 0 ;
2003-03-01 23:34:34 +01:00
opt_reconnect = 0 ;
2002-08-06 21:51:43 +02:00
connect_flag = 0 ; /* Not in interactive mode */
2000-11-17 13:33:29 +01:00
}
2006-04-18 10:16:06 +02:00
2004-02-11 12:15:39 +01:00
if ( strcmp ( default_charset , charset_info - > csname ) & &
! ( charset_info = get_charset_by_csname ( default_charset ,
2003-05-22 11:37:01 +02:00
MY_CS_PRIMARY , MYF ( MY_WME ) ) ) )
2003-03-16 08:20:45 +01:00
exit ( 1 ) ;
2000-07-31 21:29:14 +02:00
if ( argc > 1 )
{
usage ( 0 ) ;
exit ( 1 ) ;
}
if ( argc = = 1 )
{
2003-03-17 14:50:56 +01:00
skip_updates = 0 ;
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 ) ;
2009-05-07 19:28:29 +02:00
if ( ignore_spaces )
connect_flag | = CLIENT_IGNORE_SPACE ;
2000-07-31 21:29:14 +02:00
return ( 0 ) ;
}
2005-08-09 21:17:28 +02:00
static int read_and_execute ( bool interactive )
2000-07-31 21:29:14 +02:00
{
2005-09-15 23:56:16 +02:00
# if defined(OS2) || defined(__NETWARE__)
2000-07-31 21:29:14 +02:00
char linebuffer [ 254 ] ;
2005-06-09 19:44:59 +02:00
String buffer ;
2000-07-31 21:29:14 +02:00
# endif
2005-09-15 23:56:16 +02:00
# if defined(__WIN__)
String tmpbuf ;
String buffer ;
# endif
2000-07-31 21:29:14 +02:00
char * line ;
char in_string = 0 ;
ulong line_number = 0 ;
2002-12-23 23:53:07 +01:00
bool ml_comment = 0 ;
2000-07-31 21:29:14 +02:00
COMMANDS * com ;
2009-03-18 09:18:24 +01:00
bool truncated = 0 ;
2000-07-31 21:29:14 +02:00
status . exit_status = 1 ;
2002-12-23 23:53:07 +01:00
2000-07-31 21:29:14 +02:00
for ( ; ; )
{
2005-08-09 21:17:28 +02:00
if ( ! interactive )
2000-07-31 21:29:14 +02:00
{
2009-03-18 09:18:24 +01:00
line = batch_readline ( status . line_buff , & truncated ) ;
2007-10-04 10:06:01 +02:00
/*
Skip UTF8 Byte Order Marker ( BOM ) 0xEFBBBF .
Editors like " notepad " put this marker in
the very beginning of a text file when
you save the file using " Unicode UTF-8 " format .
*/
2008-06-24 18:05:56 +02:00
if ( line & & ! line_number & &
2007-10-04 10:06:01 +02:00
( uchar ) line [ 0 ] = = 0xEF & &
( uchar ) line [ 1 ] = = 0xBB & &
( uchar ) line [ 2 ] = = 0xBF )
line + = 3 ;
2000-07-31 21:29:14 +02:00
line_number + + ;
if ( ! glob_buffer . length ( ) )
status . query_start_line = line_number ;
}
else
2000-11-17 13:33:29 +01:00
{
2005-03-16 02:33:06 +01:00
char * prompt = ( char * ) ( ml_comment ? " /*> " :
glob_buffer . is_empty ( ) ? construct_prompt ( ) :
2003-01-28 07:38:28 +01:00
! in_string ? " -> " :
in_string = = ' \' ' ?
2003-09-17 20:41:36 +02:00
" '> " : ( in_string = = ' ` ' ?
" `> " :
" \" > " ) ) ;
2000-11-22 02:45:02 +01:00
if ( opt_outfile & & glob_buffer . is_empty ( ) )
fflush ( OUTFILE ) ;
2003-01-28 07:38:28 +01:00
2006-08-10 03:46:46 +02:00
interrupted_query = 0 ;
2003-01-28 07:38:28 +01:00
# if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
tee_fputs ( prompt , stdout ) ;
2005-09-15 23:56:16 +02:00
# if defined(__NETWARE__)
2003-01-28 07:38:28 +01:00
line = fgets ( linebuffer , sizeof ( linebuffer ) - 1 , stdin ) ;
/* Remove the '\n' */
2004-05-25 21:00:14 +02:00
if ( line )
2000-11-17 20:36:47 +01:00
{
2003-01-28 07:38:28 +01:00
char * p = strrchr ( line , ' \n ' ) ;
2003-03-21 22:45:39 +01:00
if ( p ! = NULL )
* p = ' \0 ' ;
2000-11-17 20:36:47 +01:00
}
2005-09-15 23:56:16 +02:00
# elif defined(__WIN__)
if ( ! tmpbuf . is_alloced ( ) )
tmpbuf . alloc ( 65535 ) ;
2005-10-19 00:53:09 +02:00
tmpbuf . length ( 0 ) ;
2005-09-15 23:56:16 +02:00
buffer . length ( 0 ) ;
unsigned long clen ;
do
{
2005-10-19 00:53:09 +02:00
line = my_cgets ( ( char * ) tmpbuf . ptr ( ) , tmpbuf . alloced_length ( ) - 1 , & clen ) ;
2005-09-15 23:56:16 +02:00
buffer . append ( line , clen ) ;
/*
if we got buffer fully filled than there is a chance that
something else is still in console input buffer
*/
2005-09-25 20:22:23 +02:00
} while ( tmpbuf . alloced_length ( ) < = clen ) ;
2007-07-10 09:43:12 +02:00
/*
An empty line is returned from my_cgets when there ' s error reading :
Ctrl - c for example
*/
if ( line )
line = buffer . c_ptr ( ) ;
2005-09-15 23:56:16 +02:00
# else /* OS2 */
2005-06-09 19:44:59 +02:00
buffer . length ( 0 ) ;
2005-06-08 00:43:57 +02:00
/* _cgets() expects the buffer size - 3 as the first byte */
linebuffer [ 0 ] = ( char ) sizeof ( linebuffer ) - 3 ;
2005-06-09 19:44:59 +02:00
do
{
line = _cgets ( linebuffer ) ;
buffer . append ( line , ( unsigned char ) linebuffer [ 1 ] ) ;
/*
If _cgets ( ) gets an input line that is linebuffer [ 0 ] bytes
long , the next call to _cgets ( ) will return immediately with
linebuffer [ 1 ] = = 0 , and it does the same thing for input that
is linebuffer [ 0 ] - 1 bytes long . So it appears that even though
_cgets ( ) replaces the newline ( which is two bytes on Window ) with
a nil , it still needs the space in the linebuffer for it . This is ,
naturally , undocumented .
*/
2005-06-20 18:54:45 +02:00
} while ( ( unsigned char ) linebuffer [ 0 ] < =
( unsigned char ) linebuffer [ 1 ] + 1 ) ;
2005-06-09 19:44:59 +02:00
line = buffer . c_ptr ( ) ;
2003-01-28 07:38:28 +01:00
# endif /* __NETWARE__ */
# else
if ( opt_outfile )
fputs ( prompt , OUTFILE ) ;
line = readline ( prompt ) ;
# endif /* defined( __WIN__) || defined(OS2) || defined(__NETWARE__) */
2004-05-25 21:00:14 +02:00
/*
When Ctrl + d or Ctrl + z is pressed , the line may be NULL on some OS
which may cause coredump .
*/
if ( opt_outfile & & line )
2000-11-17 20:36:47 +01:00
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 ;
}
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
*/
2005-08-09 21:17:28 +02:00
if ( ( named_cmds | | glob_buffer . is_empty ( ) )
2006-07-13 09:04:06 +02:00
& & ! ml_comment & & ! 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
2005-08-09 21:17:28 +02:00
if ( interactive & & status . add_to_history & & not_in_history ( line ) )
2000-07-31 21:29:14 +02:00
add_history ( line ) ;
# endif
continue ;
}
2009-03-18 09:18:24 +01:00
if ( add_line ( glob_buffer , line , & in_string , & ml_comment , truncated ) )
2000-07-31 21:29:14 +02:00
break ;
}
/* if in batch mode, send last query even if it doesn't end with \g or go */
2005-08-09 21:17:28 +02:00
if ( ! interactive & & ! status . exit_status )
2000-07-31 21:29:14 +02:00
{
remove_cntrl ( glob_buffer ) ;
if ( ! glob_buffer . is_empty ( ) )
{
status . exit_status = 1 ;
if ( com_go ( & glob_buffer , line ) < = 0 )
status . exit_status = 0 ;
}
}
2005-09-15 23:56:16 +02:00
2005-06-09 19:44:59 +02:00
# if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
buffer . free ( ) ;
# endif
2005-09-15 23:56:16 +02:00
# if defined( __WIN__)
tmpbuf . free ( ) ;
# endif
2000-07-31 21:29:14 +02:00
return status . exit_status ;
}
2005-10-06 16:54:43 +02:00
static COMMANDS * find_command ( char * name , char cmd_char )
2000-07-31 21:29:14 +02:00
{
uint len ;
char * end ;
2005-10-06 16:54:43 +02:00
DBUG_ENTER ( " find_command " ) ;
DBUG_PRINT ( " enter " , ( " name: '%s' char: %d " , name ? name : " NULL " , cmd_char ) ) ;
2000-07-31 21:29:14 +02:00
if ( ! name )
{
len = 0 ;
end = 0 ;
}
else
{
2003-03-16 08:20:45 +01:00
while ( my_isspace ( charset_info , * name ) )
2000-07-31 21:29:14 +02:00
name + + ;
2005-03-08 17:12:12 +01:00
/*
2005-10-06 16:54:43 +02:00
If there is an \ \ g in the row or if the row has a delimiter but
this is not a delimiter command , let add_line ( ) take care of
parsing the row and calling find_command ( )
2005-03-08 17:12:12 +01:00
*/
if ( strstr ( name , " \\ g " ) | | ( strstr ( name , delimiter ) & &
2005-10-28 01:13:34 +02:00
! ( strlen ( name ) > = 9 & &
2009-05-28 10:34:30 +02:00
! my_strnncoll ( & my_charset_latin1 ,
2005-10-28 01:13:34 +02:00
( uchar * ) name , 9 ,
( const uchar * ) " delimiter " ,
9 ) ) ) )
2005-10-06 16:54:43 +02:00
DBUG_RETURN ( ( COMMANDS * ) 0 ) ;
2000-07-31 21:29:14 +02:00
if ( ( end = strcont ( name , " \t " ) ) )
{
len = ( uint ) ( end - name ) ;
2003-03-16 08:20:45 +01:00
while ( my_isspace ( 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 & &
2005-10-06 16:54:43 +02:00
( ( name & &
2009-05-28 10:34:30 +02:00
! my_strnncoll ( & my_charset_latin1 , ( uchar * ) name , len ,
2003-04-01 11:17:28 +02:00
( uchar * ) 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 ) )
2005-10-06 16:54:43 +02:00
{
DBUG_PRINT ( " exit " , ( " found command: %s " , commands [ i ] . name ) ) ;
DBUG_RETURN ( & commands [ i ] ) ;
}
2000-07-31 21:29:14 +02:00
}
2005-10-06 16:54:43 +02:00
DBUG_RETURN ( ( COMMANDS * ) 0 ) ;
2000-07-31 21:29:14 +02:00
}
2002-12-23 23:53:07 +01:00
static bool add_line ( String & buffer , char * line , char * in_string ,
2009-03-18 09:18:24 +01:00
bool * ml_comment , bool truncated )
2000-07-31 21:29:14 +02:00
{
uchar inchar ;
2003-04-23 02:29:03 +02:00
char buff [ 80 ] , * pos , * out ;
2000-07-31 21:29:14 +02:00
COMMANDS * com ;
2005-05-08 01:13:35 +02:00
bool need_space = 0 ;
2007-08-30 10:53:24 +02:00
bool ss_comment = 0 ;
2005-10-06 16:54:43 +02:00
DBUG_ENTER ( " add_line " ) ;
2000-07-31 21:29:14 +02:00
if ( ! line [ 0 ] & & buffer . is_empty ( ) )
2005-10-06 16:54:43 +02:00
DBUG_RETURN ( 0 ) ;
2000-07-31 21:29:14 +02:00
# ifdef HAVE_READLINE
2004-03-03 21:54:37 +01:00
if ( status . add_to_history & & line [ 0 ] & & not_in_history ( line ) )
2000-07-31 21:29:14 +02:00
add_history ( line ) ;
# endif
2005-10-06 16:54:43 +02:00
char * end_of_line = line + ( uint ) strlen ( line ) ;
2000-07-31 21:29:14 +02:00
for ( pos = out = line ; ( inchar = ( uchar ) * pos ) ; pos + + )
{
2007-11-02 11:40:34 +01:00
if ( ! preserve_comments )
{
2008-12-11 18:26:03 +01:00
// Skip spaces at the beginning of a statement
2007-11-02 11:40:34 +01:00
if ( my_isspace ( charset_info , inchar ) & & ( out = = line ) & &
buffer . is_empty ( ) )
continue ;
}
2000-07-31 21:29:14 +02:00
# ifdef USE_MB
2007-11-02 11:40:34 +01:00
// Accept multi-byte characters as-is
2005-10-06 16:54:43 +02:00
int length ;
2003-03-16 08:20:45 +01:00
if ( use_mb ( charset_info ) & &
2005-10-14 11:19:15 +02:00
( length = my_ismbchar ( charset_info , pos , end_of_line ) ) )
2005-10-06 16:54:43 +02:00
{
2007-11-02 11:40:34 +01:00
if ( ! * ml_comment | | preserve_comments )
2005-09-28 12:46:09 +02:00
{
2005-10-14 11:19:15 +02:00
while ( length - - )
2005-09-28 12:46:09 +02:00
* out + + = * pos + + ;
pos - - ;
}
else
2005-10-14 11:19:15 +02:00
pos + = length - 1 ;
2005-10-06 16:54:43 +02:00
continue ;
2000-07-31 21:29:14 +02:00
}
# endif
2006-08-01 10:05:54 +02:00
if ( ! * ml_comment & & inchar = = ' \\ ' & &
! ( mysql . server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES ) )
2003-04-23 02:29:03 +02:00
{
// Found possbile one character command like \c
2000-07-31 21:29:14 +02:00
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 ) ) )
{
2007-11-02 11:40:34 +01:00
// Flush previously accepted characters
if ( out ! = line )
{
buffer . append ( line , ( uint ) ( out - line ) ) ;
out = line ;
}
2007-08-30 10:53:24 +02:00
if ( ( * com - > func ) ( & buffer , pos - 1 ) > 0 )
DBUG_RETURN ( 1 ) ; // Quit
if ( com - > takes_params )
{
if ( ss_comment )
{
/*
If a client - side macro appears inside a server - side comment ,
discard all characters in the comment after the macro ( that is ,
until the end of the comment rather than the next delimiter )
*/
for ( pos + + ; * pos & & ( * pos ! = ' * ' | | * ( pos + 1 ) ! = ' / ' ) ; pos + + )
;
pos - - ;
}
else
{
for ( pos + + ;
* pos & & ( * pos ! = * delimiter | |
! is_prefix ( pos + 1 , delimiter + 1 ) ) ; pos + + )
; // Remove parameters
if ( ! * pos )
pos - - ;
else
pos + = delimiter_length - 1 ; // Point at last delim char
}
}
2000-07-31 21:29:14 +02:00
}
else
{
sprintf ( buff , " Unknown command ' \\ %c'. " , inchar ) ;
if ( put_info ( buff , INFO_ERROR ) > 0 )
2005-10-06 16:54:43 +02:00
DBUG_RETURN ( 1 ) ;
2000-07-31 21:29:14 +02:00
* out + + = ' \\ ' ;
* out + + = ( char ) inchar ;
continue ;
}
}
2007-11-02 11:40:34 +01:00
else if ( ! * ml_comment & & ! * in_string & & is_prefix ( pos , delimiter ) )
{
// Found a statement. Continue parsing after the delimiter
pos + = delimiter_length ;
if ( preserve_comments )
{
while ( my_isspace ( charset_info , * pos ) )
* out + + = * pos + + ;
}
// Flush previously accepted characters
2000-07-31 21:29:14 +02:00
if ( out ! = line )
2007-11-02 11:40:34 +01:00
{
buffer . append ( line , ( uint32 ) ( out - line ) ) ;
out = line ;
}
if ( preserve_comments & & ( ( * pos = = ' # ' ) | |
( ( * pos = = ' - ' ) & &
( pos [ 1 ] = = ' - ' ) & &
my_isspace ( charset_info , pos [ 2 ] ) ) ) )
{
// Add trailing single line comments to this statement
buffer . append ( pos ) ;
pos + = strlen ( pos ) ;
}
pos - - ;
2003-04-23 02:29:03 +02:00
if ( ( com = find_command ( buffer . c_ptr ( ) , 0 ) ) )
2000-07-31 21:29:14 +02:00
{
2007-11-02 11:40:34 +01:00
if ( ( * com - > func ) ( & buffer , buffer . c_ptr ( ) ) > 0 )
DBUG_RETURN ( 1 ) ; // Quit
2000-07-31 21:29:14 +02:00
}
else
{
2007-11-02 11:40:34 +01:00
if ( com_go ( & buffer , 0 ) > 0 ) // < 0 is not fatal
DBUG_RETURN ( 1 ) ;
2000-07-31 21:29:14 +02:00
}
buffer . length ( 0 ) ;
}
2002-12-23 23:53:07 +01:00
else if ( ! * ml_comment & & ( ! * in_string & & ( inchar = = ' # ' | |
inchar = = ' - ' & & pos [ 1 ] = = ' - ' & &
2008-06-24 16:32:06 +02:00
/*
The third byte is either whitespace or is the
end of the line - - which would occur only
because of the user sending newline - - which is
itself whitespace and should also match .
*/
( my_isspace ( charset_info , pos [ 2 ] ) | |
! pos [ 2 ] ) ) ) )
2007-11-02 11:40:34 +01:00
{
// Flush previously accepted characters
if ( out ! = line )
{
buffer . append ( line , ( uint32 ) ( out - line ) ) ;
out = line ;
}
// comment to end of line
if ( preserve_comments )
2008-12-11 18:26:03 +01:00
{
bool started_with_nothing = ! buffer . length ( ) ;
2007-11-02 11:40:34 +01:00
buffer . append ( pos ) ;
2008-12-11 18:26:03 +01:00
/*
A single - line comment by itself gets sent immediately so that
client commands ( delimiter , status , etc ) will be interpreted on
the next line .
*/
if ( started_with_nothing )
{
if ( com_go ( & buffer , 0 ) > 0 ) // < 0 is not fatal
DBUG_RETURN ( 1 ) ;
buffer . length ( 0 ) ;
}
}
2007-11-02 11:40:34 +01:00
break ;
}
2003-04-23 02:29:03 +02:00
else if ( ! * in_string & & inchar = = ' / ' & & * ( pos + 1 ) = = ' * ' & &
* ( pos + 2 ) ! = ' ! ' )
2002-12-23 23:53:07 +01:00
{
2007-11-02 11:40:34 +01:00
if ( preserve_comments )
{
* out + + = * pos + + ; // copy '/'
* out + + = * pos ; // copy '*'
}
else
pos + + ;
2002-12-23 23:53:07 +01:00
* ml_comment = 1 ;
if ( out ! = line )
{
buffer . append ( line , ( uint ) ( out - line ) ) ;
out = line ;
}
}
2007-08-30 10:53:24 +02:00
else if ( * ml_comment & & ! ss_comment & & inchar = = ' * ' & & * ( pos + 1 ) = = ' / ' )
2002-12-23 23:53:07 +01:00
{
2007-11-02 11:40:34 +01:00
if ( preserve_comments )
{
* out + + = * pos + + ; // copy '*'
* out + + = * pos ; // copy '/'
}
else
pos + + ;
2002-12-23 23:53:07 +01:00
* ml_comment = 0 ;
2007-11-02 11:40:34 +01:00
if ( out ! = line )
{
buffer . append ( line , ( uint32 ) ( out - line ) ) ;
out = line ;
}
// Consumed a 2 chars or more, and will add 1 at most,
// so using the 'line' buffer to edit data in place is ok.
2005-05-08 01:13:35 +02:00
need_space = 1 ;
2002-12-23 23:53:07 +01:00
}
2000-07-31 21:29:14 +02:00
else
{ // Add found char to buffer
2007-08-30 10:53:24 +02:00
if ( ! * in_string & & inchar = = ' / ' & & * ( pos + 1 ) = = ' * ' & &
* ( pos + 2 ) = = ' ! ' )
ss_comment = 1 ;
else if ( ! * in_string & & ss_comment & & inchar = = ' * ' & & * ( pos + 1 ) = = ' / ' )
ss_comment = 0 ;
2000-07-31 21:29:14 +02:00
if ( inchar = = * in_string )
2003-07-15 11:38:48 +02:00
* in_string = 0 ;
2003-07-15 14:38:01 +02:00
else if ( ! * ml_comment & & ! * in_string & &
( inchar = = ' \' ' | | inchar = = ' " ' | | inchar = = ' ` ' ) )
* in_string = ( char ) inchar ;
2007-11-02 11:40:34 +01:00
if ( ! * ml_comment | | preserve_comments )
2005-05-08 01:13:35 +02:00
{
if ( need_space & & ! my_isspace ( charset_info , ( char ) inchar ) )
* out + + = ' ' ;
2007-11-02 11:40:34 +01:00
need_space = 0 ;
* out + + = ( char ) inchar ;
2005-05-08 01:13:35 +02:00
}
2000-07-31 21:29:14 +02:00
}
}
if ( out ! = line | | ! buffer . is_empty ( ) )
{
uint length = ( uint ) ( out - line ) ;
2009-02-24 14:06:28 +01:00
2009-03-18 09:18:24 +01:00
if ( ! truncated & &
( length < 9 | |
my_strnncoll ( charset_info ,
( uchar * ) line , 9 , ( const uchar * ) " delimiter " , 9 ) ) )
2009-02-24 14:06:28 +01:00
{
/*
Don ' t add a new line in case there ' s a DELIMITER command to be
added to the glob buffer ( e . g . on processing a line like
" <command>;DELIMITER <non-eof> " ) : similar to how a new line is
not added in the case when the DELIMITER is the first command
entered with an empty glob buffer .
*/
* out + + = ' \n ' ;
length + + ;
}
2000-07-31 21:29:14 +02:00
if ( buffer . length ( ) + length > = buffer . alloced_length ( ) )
buffer . realloc ( buffer . length ( ) + length + IO_SIZE ) ;
2007-11-02 11:40:34 +01:00
if ( ( ! * ml_comment | | preserve_comments ) & & buffer . append ( line , length ) )
2005-10-06 16:54:43 +02:00
DBUG_RETURN ( 1 ) ;
2000-07-31 21:29:14 +02:00
}
2005-10-06 16:54:43 +02:00
DBUG_RETURN ( 0 ) ;
2000-07-31 21:29:14 +02:00
}
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
2009-02-10 13:39:14 +01:00
# if defined(USE_NEW_READLINE_INTERFACE)
2003-01-18 17:28:48 +01:00
char * no_completion ( const char * , int )
2009-02-10 13:39:14 +01:00
# elif defined(USE_LIBEDIT_INTERFACE)
int no_completion ( const char * , int )
2003-01-18 17:28:48 +01:00
# else
2007-01-31 15:25:56 +01:00
char * no_completion ( )
2003-01-18 17:28:48 +01:00
# endif
2000-07-31 21:29:14 +02:00
{
return 0 ; /* No filename completion */
}
2004-03-03 21:54:37 +01:00
/* glues pieces of history back together if in pieces */
static void fix_history ( String * final_command )
{
int total_lines = 1 ;
char * ptr = final_command - > c_ptr ( ) ;
String fixed_buffer ; /* Converted buffer */
char str_char = ' \0 ' ; /* Character if we are in a string or not */
/* find out how many lines we have and remove newlines */
while ( * ptr ! = ' \0 ' )
{
switch ( * ptr ) {
/* string character */
case ' " ' :
case ' \' ' :
case ' ` ' :
if ( str_char = = ' \0 ' ) /* open string */
str_char = * ptr ;
else if ( str_char = = * ptr ) /* close string */
str_char = ' \0 ' ;
fixed_buffer . append ( ptr , 1 ) ;
break ;
case ' \n ' :
/*
not in string , change to space
if in string , leave it alone
*/
fixed_buffer . append ( str_char = = ' \0 ' ? " " : " \n " ) ;
total_lines + + ;
break ;
case ' \\ ' :
fixed_buffer . append ( ' \\ ' ) ;
/* need to see if the backslash is escaping anything */
if ( str_char )
{
ptr + + ;
/* special characters that need escaping */
if ( * ptr = = ' \' ' | | * ptr = = ' " ' | | * ptr = = ' \\ ' )
fixed_buffer . append ( ptr , 1 ) ;
else
ptr - - ;
}
break ;
default :
fixed_buffer . append ( ptr , 1 ) ;
}
ptr + + ;
}
if ( total_lines > 1 )
add_history ( fixed_buffer . ptr ( ) ) ;
}
/*
returns 0 if line matches the previous history entry
returns 1 if the line doesn ' t match the previous history entry
*/
static int not_in_history ( const char * line )
{
HIST_ENTRY * oldhist = history_get ( history_length ) ;
if ( oldhist = = 0 )
return 1 ;
if ( strcmp ( oldhist - > line , line ) = = 0 )
return 0 ;
return 1 ;
}
2000-07-31 21:29:14 +02:00
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. */
2003-01-18 17:28:48 +01:00
# if defined(USE_NEW_READLINE_INTERFACE)
rl_attempted_completion_function = ( rl_completion_func_t * ) & new_mysql_completion ;
rl_completion_entry_function = ( rl_compentry_func_t * ) & no_completion ;
# elif defined(USE_LIBEDIT_INTERFACE)
2003-04-07 02:14:36 +02:00
# ifdef HAVE_LOCALE_H
setlocale ( LC_ALL , " " ) ; /* so as libedit use isprint */
# endif
2003-01-18 17:28:48 +01:00
rl_attempted_completion_function = ( CPPFunction * ) & new_mysql_completion ;
2007-01-31 15:25:56 +01:00
rl_completion_entry_function = & no_completion ;
2002-11-26 14:03:25 +01:00
# else
2003-01-18 17:28:48 +01:00
rl_attempted_completion_function = ( CPPFunction * ) & new_mysql_completion ;
2007-01-31 15:25:56 +01:00
rl_completion_entry_function = & no_completion ;
2002-11-26 14:03:25 +01:00
# 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 )
2003-01-18 17:28:48 +01:00
# if defined(USE_NEW_READLINE_INTERFACE)
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
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 ) ) ;
2008-01-30 22:51:39 +01:00
/* hash this file's known subset of SQL commands */
while ( cmd - > name ) {
add_word ( & ht , ( char * ) cmd - > name ) ;
cmd + + ;
}
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 ) ) ) )
2005-01-08 21:25:31 +01:00
{
mysql_free_result ( fields ) ;
break ;
}
2003-01-06 00:48:59 +01:00
field_names [ i ] [ num_fields * 2 ] = ' \0 ' ;
2000-07-31 21:29:14 +02:00
j = 0 ;
while ( ( sql_field = mysql_fetch_field ( fields ) ) )
{
2005-01-14 22:46:04 +01:00
sprintf ( buf , " %.64s.%.64s " , 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
2003-01-06 00:48:59 +01:00
field_names [ i ] = 0 ;
2005-08-08 22:50:10 +02:00
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 )
{
2006-12-14 23:51:37 +01:00
/* purecov: begin tested */
2003-03-01 23:34:34 +01:00
if ( opt_reconnect )
2000-07-31 21:29:14 +02:00
{
put_info ( " No connection. Trying to reconnect... " , INFO_INFO ) ;
( void ) com_connect ( ( String * ) 0 , 0 ) ;
2006-12-14 23:51:37 +01:00
if ( opt_rehash )
2002-06-11 10:20:31 +02:00
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 ) ;
2006-12-14 23:51:37 +01:00
/* purecov: end */
2000-07-31 21:29:14 +02:00
return 0 ;
}
2004-10-21 14:02:24 +02:00
static void get_current_db ( )
{
MYSQL_RES * res ;
my_free ( current_db , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
current_db = NULL ;
/* In case of error below current_db will be NULL */
if ( ! mysql_query ( & mysql , " SELECT DATABASE() " ) & &
( res = mysql_use_result ( & mysql ) ) )
{
MYSQL_ROW row = mysql_fetch_row ( res ) ;
2009-03-23 05:08:32 +01:00
if ( row & & row [ 0 ] )
2004-10-21 14:02:24 +02:00
current_db = my_strdup ( row [ 0 ] , MYF ( MY_WME ) ) ;
mysql_free_result ( res ) ;
}
}
2000-07-31 21:29:14 +02:00
/***************************************************************************
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 + + )
{
2005-06-01 15:35:09 +02:00
int error ;
2002-10-28 14:44:19 +01:00
if ( ! mysql_real_query ( & mysql , buf , length ) )
2005-01-14 22:46:04 +01:00
return 0 ;
2005-06-01 15:35:09 +02:00
error = put_error ( & mysql ) ;
2003-02-12 20:55:37 +01:00
if ( mysql_errno ( & mysql ) ! = CR_SERVER_GONE_ERROR | | retry > 1 | |
2005-06-01 15:35:09 +02:00
! opt_reconnect )
2002-10-28 14:44:19 +01:00
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 ] )
2003-06-04 17:28:51 +02:00
return put_error ( & mysql ) ;
2002-10-28 14:44:19 +01:00
return 0 ;
}
2003-05-29 23:47:31 +02:00
static void print_help_item ( MYSQL_ROW * cur , int num_name , int num_cat , char * last_char )
{
char ccat = ( * cur ) [ num_cat ] [ 0 ] ;
if ( * last_char ! = ccat )
{
2004-11-19 21:53:40 +01:00
put_info ( ccat = = ' Y ' ? " categories: " : " topics: " , INFO_INFO ) ;
2003-05-29 23:47:31 +02:00
* last_char = ccat ;
}
tee_fprintf ( PAGER , " %s \n " , ( * cur ) [ num_name ] ) ;
}
2003-02-12 20:55:37 +01:00
2003-10-06 21:56:34 +02:00
2002-10-28 14:44:19 +01:00
static int com_server_help ( String * buffer __attribute__ ( ( unused ) ) ,
2003-02-12 20:55:37 +01:00
char * line __attribute__ ( ( unused ) ) , char * help_arg )
2002-10-28 14:44:19 +01:00
{
MYSQL_ROW cur ;
const char * server_cmd = buffer - > ptr ( ) ;
char cmd_buf [ 100 ] ;
2003-01-06 00:48:59 +01:00
MYSQL_RES * result ;
int error ;
2003-05-29 23:47:31 +02:00
2003-01-06 00:48:59 +01:00
if ( help_arg [ 0 ] ! = ' \' ' )
2002-10-28 14:44:19 +01:00
{
2006-06-29 23:06:28 +02:00
char * end_arg = strend ( help_arg ) ;
if ( - - end_arg )
{
while ( my_isspace ( charset_info , * end_arg ) )
end_arg - - ;
* + + end_arg = ' \0 ' ;
}
( void ) strxnmov ( cmd_buf , sizeof ( cmd_buf ) , " help ' " , help_arg , " ' " , NullS ) ;
2002-10-28 14:44:19 +01:00
server_cmd = cmd_buf ;
}
2003-05-29 23:47:31 +02:00
2002-10-28 14:44:19 +01:00
if ( ! status . batch )
{
old_buffer = * buffer ;
old_buffer . copy ( ) ;
}
if ( ! connected & & reconnect ( ) )
return 1 ;
2005-03-07 09:47:24 +01:00
if ( ( error = mysql_real_query_for_lazy ( server_cmd , ( int ) strlen ( server_cmd ) ) ) | |
2003-05-29 23:47:31 +02:00
( error = mysql_store_result_for_lazy ( & result ) ) )
2002-10-28 14:44:19 +01:00
return error ;
if ( result )
{
2003-05-29 23:47:31 +02:00
unsigned int num_fields = mysql_num_fields ( result ) ;
my_ulonglong num_rows = mysql_num_rows ( result ) ;
2004-05-19 04:09:10 +02:00
mysql_fetch_fields ( result ) ;
2003-05-29 23:47:31 +02:00
if ( num_fields = = 3 & & num_rows = = 1 )
2002-10-28 14:44:19 +01:00
{
if ( ! ( cur = mysql_fetch_row ( result ) ) )
2003-01-06 00:48:59 +01:00
{
error = - 1 ;
goto err ;
}
2002-10-28 14:44:19 +01:00
init_pager ( ) ;
2003-05-29 23:47:31 +02:00
tee_fprintf ( PAGER , " Name: \' %s \' \n " , cur [ 0 ] ) ;
tee_fprintf ( PAGER , " Description: \n %s " , cur [ 1 ] ) ;
if ( cur [ 2 ] & & * ( ( char * ) cur [ 2 ] ) )
tee_fprintf ( PAGER , " Examples: \n %s " , cur [ 2 ] ) ;
tee_fprintf ( PAGER , " \n " ) ;
2002-10-28 14:44:19 +01:00
end_pager ( ) ;
}
2003-05-29 23:47:31 +02:00
else if ( num_fields > = 2 & & num_rows )
2002-10-28 14:44:19 +01:00
{
init_pager ( ) ;
2005-01-24 15:48:25 +01:00
char last_char = 0 ;
2004-01-14 16:48:38 +01:00
int num_name = 0 , num_cat = 0 ;
2003-06-14 10:37:42 +02:00
LINT_INIT ( num_name ) ;
LINT_INIT ( num_cat ) ;
2003-05-29 23:47:31 +02:00
if ( num_fields = = 2 )
2003-01-06 00:48:59 +01:00
{
2004-11-19 21:53:40 +01:00
put_info ( " Many help items for your request exist. " , INFO_INFO ) ;
2004-12-18 21:30:00 +01:00
put_info ( " To make a more specific request, please type 'help <item>', \n where <item> is one of the following " , INFO_INFO ) ;
2003-05-29 23:47:31 +02:00
num_name = 0 ;
num_cat = 1 ;
2002-10-28 14:44:19 +01:00
}
2003-05-29 23:47:31 +02:00
else if ( ( cur = mysql_fetch_row ( result ) ) )
{
2004-08-27 19:27:57 +02:00
tee_fprintf ( PAGER , " You asked for help about help category: \" %s \" \n " , cur [ 0 ] ) ;
2004-12-18 21:30:00 +01:00
put_info ( " For more information, type 'help <item>', where <item> is one of the following " , INFO_INFO ) ;
2003-05-29 23:47:31 +02:00
num_name = 1 ;
num_cat = 2 ;
print_help_item ( & cur , 1 , 2 , & last_char ) ;
}
2005-01-24 15:48:25 +01:00
2003-05-29 23:47:31 +02:00
while ( ( cur = mysql_fetch_row ( result ) ) )
print_help_item ( & cur , num_name , num_cat , & last_char ) ;
2002-10-28 14:44:19 +01:00
tee_fprintf ( PAGER , " \n " ) ;
end_pager ( ) ;
}
else
{
2003-05-29 23:47:31 +02:00
put_info ( " \n Nothing found " , INFO_INFO ) ;
2004-08-27 19:27:57 +02:00
put_info ( " Please try to run 'help contents' for a list of all accessible topics \n " , INFO_INFO ) ;
2002-10-28 14:44:19 +01:00
}
}
2003-01-06 00:48:59 +01:00
err :
2002-10-28 14:44:19 +01:00
mysql_free_result ( result ) ;
return error ;
}
2000-07-31 21:29:14 +02:00
static int
2003-02-12 20:55:37 +01:00
com_help ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
2000-07-31 21:29:14 +02:00
{
2003-12-30 16:58:39 +01:00
reg1 int i , j ;
char * help_arg = strchr ( line , ' ' ) , buff [ 32 ] , * end ;
2002-10-28 14:44:19 +01:00
if ( help_arg )
2006-06-29 23:06:28 +02:00
{
while ( my_isspace ( charset_info , * help_arg ) )
help_arg + + ;
if ( * help_arg )
return com_server_help ( buffer , line , help_arg ) ;
}
2003-10-06 21:56:34 +02:00
2005-11-12 00:23:04 +01:00
put_info ( " \n For information about MySQL products and services, visit: \n "
" http://www.mysql.com/ \n "
" For developer information, including the MySQL Reference Manual, "
" visit: \n "
" http://dev.mysql.com/ \n "
" To buy MySQL Network Support, training, or other products, visit: \n "
" https://shop.mysql.com/ \n " , INFO_INFO ) ;
2003-10-06 21:56:34 +02:00
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 + + )
2002-10-28 14:44:19 +01:00
{
2003-12-30 16:58:39 +01:00
end = strmov ( buff , commands [ i ] . name ) ;
2005-03-07 09:47:24 +01:00
for ( j = ( int ) strlen ( commands [ i ] . name ) ; j < 10 ; j + + )
2003-12-30 16:58:39 +01:00
end = strmov ( end , " " ) ;
2003-10-06 21:56:34 +02:00
if ( commands [ i ] . func )
2003-12-30 16:58:39 +01:00
tee_fprintf ( stdout , " %s( \\ %c) %s \n " , buff ,
2003-10-06 21:56:34 +02:00
commands [ i ] . cmd_char , commands [ i ] . doc ) ;
2002-10-28 14:44:19 +01:00
}
2003-02-12 20:55:37 +01:00
if ( connected & & mysql_get_server_version ( & mysql ) > = 40100 )
2004-07-13 08:57:55 +02:00
put_info ( " \n For server side help, type 'help contents' \n " , INFO_INFO ) ;
2000-07-31 21:29:14 +02:00
return 0 ;
}
/* ARGSUSED */
static int
com_clear ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
2004-03-03 21:54:37 +01:00
# ifdef HAVE_READLINE
if ( status . add_to_history )
fix_history ( buffer ) ;
# endif
2000-07-31 21:29:14 +02:00
buffer - > length ( 0 ) ;
return 0 ;
}
2006-02-09 15:23:09 +01:00
/* ARGSUSED */
static int
com_charset ( String * buffer __attribute__ ( ( unused ) ) , char * line )
{
char buff [ 256 ] , * param ;
CHARSET_INFO * new_cs ;
strmake ( buff , line , sizeof ( buff ) - 1 ) ;
param = get_arg ( buff , 0 ) ;
if ( ! param | | ! * param )
{
2009-02-19 04:58:10 +01:00
return put_info ( " Usage: \\ C charset_name | charset charset_name " ,
2006-02-09 15:23:09 +01:00
INFO_ERROR , 0 ) ;
}
new_cs = get_charset_by_csname ( param , MY_CS_PRIMARY , MYF ( MY_WME ) ) ;
if ( new_cs )
{
charset_info = new_cs ;
2006-08-24 17:15:08 +02:00
mysql_set_character_set ( & mysql , charset_info - > csname ) ;
default_charset = ( char * ) charset_info - > csname ;
default_charset_used = 1 ;
2006-02-09 15:23:09 +01:00
put_info ( " Charset changed " , INFO_INFO ) ;
}
else put_info ( " Charset is not found " , INFO_INFO ) ;
return 0 ;
}
2000-07-31 21:29:14 +02:00
/*
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 ) ) )
{
2008-01-25 16:53:21 +01:00
char buff [ 200 ] ; /* about 110 chars used so far */
char time_buff [ 52 + 3 + 1 ] ; /* time max + space&parens + NUL */
2000-07-31 21:29:14 +02:00
MYSQL_RES * result ;
2002-10-02 12:33:08 +02:00
ulong timer , warnings ;
2003-11-20 19:06:51 +01:00
uint error = 0 ;
int err = 0 ;
2000-07-31 21:29:14 +02:00
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
2003-03-01 23:34:34 +01:00
return opt_reconnect ? - 1 : 1 ; // Fatal error
2000-07-31 21:29:14 +02:00
}
if ( verbose )
( void ) com_print ( buffer , 0 ) ;
if ( skip_updates & &
2003-03-16 08:20:45 +01:00
( buffer - > length ( ) < 4 | | my_strnncoll ( charset_info ,
2002-10-09 13:33:35 +02:00
( 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
2006-08-10 03:46:46 +02:00
executing_query = 1 ;
2002-10-28 14:44:19 +01:00
error = mysql_real_query_for_lazy ( buffer - > ptr ( ) , buffer - > length ( ) ) ;
2004-03-03 21:54:37 +01:00
# ifdef HAVE_READLINE
if ( status . add_to_history )
{
buffer - > append ( vertical ? " \\ G " : delimiter ) ;
/* Append final command onto history */
fix_history ( buffer ) ;
}
# endif
2002-10-28 14:44:19 +01:00
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
2006-08-10 03:46:46 +02:00
executing_query = 0 ;
2002-10-28 14:44:19 +01:00
return error ;
2000-07-31 21:29:14 +02:00
}
error = 0 ;
buffer - > length ( 0 ) ;
2003-11-20 13:33:07 +01:00
do
2000-07-31 21:29:14 +02:00
{
2008-01-25 16:53:21 +01:00
char * pos ;
2003-11-20 13:33:07 +01:00
if ( quick )
2000-07-31 21:29:14 +02:00
{
2003-11-20 13:33:07 +01:00
if ( ! ( result = mysql_use_result ( & mysql ) ) & & mysql_field_count ( & mysql ) )
2006-08-10 03:46:46 +02:00
{
executing_query = 0 ;
2003-11-20 13:33:07 +01:00
return put_error ( & mysql ) ;
2006-08-10 03:46:46 +02:00
}
2000-07-31 21:29:14 +02:00
}
else
{
2003-11-20 13:33:07 +01:00
error = mysql_store_result_for_lazy ( & result ) ;
if ( error )
2006-08-10 03:46:46 +02:00
{
executing_query = 0 ;
2003-11-20 13:33:07 +01:00
return error ;
2006-08-10 03:46:46 +02:00
}
2003-11-20 13:33:07 +01:00
}
if ( verbose > = 3 | | ! opt_silent )
mysql_end_timer ( timer , time_buff ) ;
else
2008-01-25 16:53:21 +01:00
time_buff [ 0 ] = ' \0 ' ;
/* Every branch must truncate buff . */
2003-11-20 13:33:07 +01:00
if ( result )
{
2005-06-03 21:59:33 +02:00
if ( ! mysql_num_rows ( result ) & & ! quick & & ! info_flag )
2003-11-20 13:33:07 +01:00
{
strmov ( buff , " Empty set " ) ;
2007-04-09 14:53:10 +02:00
if ( opt_xml )
{
/*
We must print XML header and footer
to produce a well - formed XML even if
the result set is empty ( Bug # 27608 ) .
*/
init_pager ( ) ;
print_table_data_xml ( result ) ;
end_pager ( ) ;
}
2003-11-20 13:33:07 +01:00
}
2000-07-31 21:29:14 +02:00
else
2003-11-20 13:33:07 +01:00
{
init_pager ( ) ;
if ( opt_html )
print_table_data_html ( result ) ;
else if ( opt_xml )
print_table_data_xml ( result ) ;
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 ) ;
sprintf ( buff , " %ld %s in set " ,
( long ) mysql_num_rows ( result ) ,
( long ) mysql_num_rows ( result ) = = 1 ? " row " : " rows " ) ;
end_pager ( ) ;
2006-11-02 11:32:00 +01:00
if ( mysql_errno ( & mysql ) )
error = put_error ( & mysql ) ;
2003-11-20 13:33:07 +01:00
}
2000-07-31 21:29:14 +02:00
}
2003-11-20 13:33:07 +01:00
else if ( mysql_affected_rows ( & mysql ) = = ~ ( ulonglong ) 0 )
strmov ( buff , " Query OK " ) ;
else
sprintf ( buff , " Query OK, %ld %s affected " ,
( long ) mysql_affected_rows ( & mysql ) ,
( long ) mysql_affected_rows ( & mysql ) = = 1 ? " row " : " rows " ) ;
pos = strend ( buff ) ;
if ( ( warnings = mysql_warning_count ( & mysql ) ) )
{
* pos + + = ' , ' ;
* pos + + = ' ' ;
2004-05-27 15:54:40 +02:00
pos = int10_to_str ( warnings , pos , 10 ) ;
2003-11-20 13:33:07 +01:00
pos = strmov ( pos , " warning " ) ;
if ( warnings ! = 1 )
* pos + + = ' s ' ;
}
strmov ( pos , time_buff ) ;
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_error ( & mysql ) ;
else if ( unbuffered )
fflush ( stdout ) ;
mysql_free_result ( result ) ;
2003-11-20 19:06:51 +01:00
} while ( ! ( err = mysql_next_result ( & mysql ) ) ) ;
2006-08-10 03:46:46 +02:00
executing_query = 0 ;
2003-11-20 19:06:51 +01:00
if ( err > = 1 )
error = put_error ( & mysql ) ;
2003-11-20 13:33:07 +01:00
2005-04-14 15:07:08 +02:00
if ( show_warnings = = 1 & & warnings > = 1 ) /* Show warnings if any */
2005-04-05 15:30:17 +02:00
{
init_pager ( ) ;
print_warnings ( ) ;
end_pager ( ) ;
}
2005-02-02 12:52:19 +01:00
if ( ! error & & ! status . batch & &
( mysql . server_status & SERVER_STATUS_DB_DROPPED ) )
2004-10-21 14:02:24 +02:00
get_current_db ( ) ;
2000-07-31 21:29:14 +02:00
return error ; /* New command follows */
}
2000-11-17 13:33:29 +01:00
static void init_pager ( )
{
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
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 ( )
{
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
2000-11-17 13:33:29 +01:00
if ( ! opt_nopager )
pclose ( PAGER ) ;
# endif
}
2002-06-12 16:35:04 +02:00
2003-01-28 07:38:28 +01:00
static void init_tee ( const char * file_name )
2000-11-17 13:33:29 +01:00
{
2002-06-12 16:35:04 +02:00
FILE * new_outfile ;
2002-05-31 11:34:47 +02:00
if ( opt_outfile )
2002-06-12 16:35:04 +02:00
end_tee ( ) ;
2003-01-28 07:38:28 +01:00
if ( ! ( new_outfile = my_fopen ( file_name , O_APPEND | O_WRONLY , MYF ( MY_WME ) ) ) )
{
tee_fprintf ( stdout , " Error logging to file '%s' \n " , file_name ) ;
return ;
}
2002-06-12 16:35:04 +02:00
OUTFILE = new_outfile ;
2003-01-28 07:38:28 +01:00
strmake ( outfile , file_name , FN_REFLEN - 1 ) ;
tee_fprintf ( stdout , " Logging to file '%s' \n " , file_name ) ;
opt_outfile = 1 ;
return ;
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 ) ) ;
2003-01-28 07:38:28 +01:00
OUTFILE = 0 ;
2002-05-31 11:34:47 +02:00
opt_outfile = 0 ;
2000-11-17 13:33:29 +01:00
return ;
}
2005-07-18 14:33:18 +02:00
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 ;
}
2005-07-18 14:33:18 +02:00
static const char * fieldtype2str ( enum enum_field_types type )
{
switch ( type ) {
2005-06-03 21:59:33 +02:00
case FIELD_TYPE_BIT : return " BIT " ;
case FIELD_TYPE_BLOB : return " BLOB " ;
case FIELD_TYPE_DATE : return " DATE " ;
case FIELD_TYPE_DATETIME : return " DATETIME " ;
case FIELD_TYPE_NEWDECIMAL : return " NEWDECIMAL " ;
case FIELD_TYPE_DECIMAL : return " DECIMAL " ;
case FIELD_TYPE_DOUBLE : return " DOUBLE " ;
case FIELD_TYPE_ENUM : return " ENUM " ;
case FIELD_TYPE_FLOAT : return " FLOAT " ;
case FIELD_TYPE_GEOMETRY : return " GEOMETRY " ;
case FIELD_TYPE_INT24 : return " INT24 " ;
case FIELD_TYPE_LONG : return " LONG " ;
case FIELD_TYPE_LONGLONG : return " LONGLONG " ;
case FIELD_TYPE_LONG_BLOB : return " LONG_BLOB " ;
case FIELD_TYPE_MEDIUM_BLOB : return " MEDIUM_BLOB " ;
case FIELD_TYPE_NEWDATE : return " NEWDATE " ;
case FIELD_TYPE_NULL : return " NULL " ;
case FIELD_TYPE_SET : return " SET " ;
case FIELD_TYPE_SHORT : return " SHORT " ;
case FIELD_TYPE_STRING : return " STRING " ;
case FIELD_TYPE_TIME : return " TIME " ;
case FIELD_TYPE_TIMESTAMP : return " TIMESTAMP " ;
case FIELD_TYPE_TINY : return " TINY " ;
case FIELD_TYPE_TINY_BLOB : return " TINY_BLOB " ;
case FIELD_TYPE_VAR_STRING : return " VAR_STRING " ;
case FIELD_TYPE_YEAR : return " YEAR " ;
default : return " ?-unknown-? " ;
}
}
static char * fieldflags2str ( uint f ) {
static char buf [ 1024 ] ;
char * s = buf ;
* s = 0 ;
# define ff2s_check_flag(X) \
if ( f & X # # _FLAG ) { s = strmov ( s , # X " " ) ; f & = ~ X # # _FLAG ; }
ff2s_check_flag ( NOT_NULL ) ;
ff2s_check_flag ( PRI_KEY ) ;
ff2s_check_flag ( UNIQUE_KEY ) ;
ff2s_check_flag ( MULTIPLE_KEY ) ;
ff2s_check_flag ( BLOB ) ;
ff2s_check_flag ( UNSIGNED ) ;
ff2s_check_flag ( ZEROFILL ) ;
ff2s_check_flag ( BINARY ) ;
ff2s_check_flag ( ENUM ) ;
ff2s_check_flag ( AUTO_INCREMENT ) ;
ff2s_check_flag ( TIMESTAMP ) ;
ff2s_check_flag ( SET ) ;
ff2s_check_flag ( NO_DEFAULT_VALUE ) ;
ff2s_check_flag ( NUM ) ;
ff2s_check_flag ( PART_KEY ) ;
ff2s_check_flag ( GROUP ) ;
ff2s_check_flag ( UNIQUE ) ;
ff2s_check_flag ( BINCMP ) ;
# undef ff2s_check_flag
if ( f )
sprintf ( s , " unknows=0x%04x " , f ) ;
return buf ;
}
2001-03-11 20:20:15 +01:00
static void
print_field_types ( MYSQL_RES * result )
{
2005-06-03 21:59:33 +02:00
MYSQL_FIELD * field ;
uint i = 0 ;
2001-03-11 20:20:15 +01:00
while ( ( field = mysql_fetch_field ( result ) ) )
{
2005-06-03 21:59:33 +02:00
tee_fprintf ( PAGER , " Field %3u: `%s` \n "
" Catalog: `%s` \n "
" Database: `%s` \n "
" Table: `%s` \n "
" Org_table: `%s` \n "
" Type: %s \n "
" Collation: %s (%u) \n "
" Length: %lu \n "
" Max_length: %lu \n "
" Decimals: %u \n "
" Flags: %s \n \n " ,
+ + i ,
field - > name , field - > catalog , field - > db , field - > table ,
field - > org_table , fieldtype2str ( field - > type ) ,
get_charset_name ( field - > charsetnr ) , field - > charsetnr ,
field - > length , field - > max_length , field - > decimals ,
fieldflags2str ( field - > flags ) ) ;
2001-03-11 20:20:15 +01:00
}
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 ) ;
2005-06-03 21:59:33 +02:00
if ( ! mysql_num_rows ( result ) )
return ;
2001-03-11 20:20:15 +01:00
mysql_field_seek ( result , 0 ) ;
}
2003-03-16 08:20:45 +01:00
separator . copy ( " + " , 1 , charset_info ) ;
2000-07-31 21:29:14 +02:00
while ( ( field = mysql_fetch_field ( result ) ) )
{
2003-02-08 00:00:35 +01:00
uint length = column_names ? field - > name_length : 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"
2006-04-16 23:17:36 +02:00
field - > max_length = length ;
2000-07-31 21:29:14 +02:00
separator . fill ( separator . length ( ) + length + 2 , ' - ' ) ;
separator . append ( ' + ' ) ;
}
2005-05-16 19:16:46 +02:00
separator . append ( ' \0 ' ) ; // End marker for \0
tee_puts ( ( char * ) separator . 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 + + )
{
2006-04-17 09:33:45 +02:00
uint name_length = ( uint ) strlen ( field - > name ) ;
uint numcells = charset_info - > cset - > numcells ( charset_info ,
field - > name ,
field - > name + name_length ) ;
uint display_length = field - > max_length + name_length - numcells ;
2006-09-01 08:53:56 +02:00
tee_fprintf ( PAGER , " %-*s | " , ( int ) min ( display_length ,
2004-10-22 17:44:51 +02:00
MAX_COLUMN_LENGTH ) ,
2006-04-17 09:33:45 +02:00
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 ) ;
2005-05-16 19:16:46 +02:00
tee_puts ( ( char * ) separator . 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
{
2004-08-25 10:03:34 +02:00
ulong * lengths = mysql_fetch_lengths ( result ) ;
2006-04-04 23:35:07 +02: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
{
2006-04-04 23:35:07 +02:00
const char * buffer ;
uint data_length ;
uint field_max_length ;
uint visible_length ;
uint extra_padding ;
2006-04-16 23:17:36 +02:00
/* If this column may have a null value, use "NULL" for empty. */
2006-09-13 17:41:41 +02:00
if ( cur [ off ] = = NULL )
2006-04-04 23:35:07 +02:00
{
buffer = " NULL " ;
data_length = 4 ;
}
else
2001-02-02 02:47:06 +01:00
{
2006-04-04 23:35:07 +02:00
buffer = cur [ off ] ;
data_length = ( uint ) lengths [ off ] ;
2001-02-02 02:47:06 +01:00
}
2006-04-04 23:35:07 +02:00
field = mysql_fetch_field ( result ) ;
field_max_length = field - > max_length ;
/*
How many text cells on the screen will this string span ? If it contains
multibyte characters , then the number of characters we occupy on screen
will be fewer than the number of bytes we occupy in memory .
We need to find how much screen real - estate we will occupy to know how
many extra padding - characters we should send with the printing function .
*/
visible_length = charset_info - > cset - > numcells ( charset_info , buffer , buffer + data_length ) ;
extra_padding = data_length - visible_length ;
if ( field_max_length > MAX_COLUMN_LENGTH )
tee_print_sized_data ( buffer , data_length , MAX_COLUMN_LENGTH + extra_padding , FALSE ) ;
2001-02-02 02:47:06 +01:00
else
2004-08-25 10:03:34 +02:00
{
2006-04-04 23:35:07 +02:00
if ( num_flag [ off ] ! = 0 ) /* if it is numeric, we right-justify it */
tee_print_sized_data ( buffer , data_length , field_max_length + extra_padding , TRUE ) ;
2006-03-03 22:26:38 +01:00
else
2006-04-04 23:35:07 +02:00
tee_print_sized_data ( buffer , data_length , field_max_length + extra_padding , FALSE ) ;
2004-08-25 10:03:34 +02:00
}
2006-04-04 23:35:07 +02:00
tee_fputs ( " | " , 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
}
2005-05-16 19:16:46 +02:00
tee_puts ( ( char * ) separator . ptr ( ) , PAGER ) ;
2000-07-31 21:29:14 +02:00
my_afree ( ( gptr ) num_flag ) ;
}
2003-01-28 07:38:28 +01:00
2006-03-03 22:26:38 +01:00
static void
2006-04-04 23:35:07 +02:00
tee_print_sized_data ( const char * data , unsigned int data_length , unsigned int total_bytes_to_send , bool right_justified )
2006-03-03 22:26:38 +01:00
{
/*
For ' \0 ' s print ASCII spaces instead , as ' \0 ' is eaten by ( at
least my ) console driver , and that messes up the pretty table
grid . ( The \ 0 is also the reason we can ' t use fprintf ( ) . )
*/
unsigned int i ;
const char * p ;
2006-04-04 23:35:07 +02:00
if ( right_justified )
2006-04-16 23:17:36 +02:00
for ( i = data_length ; i < total_bytes_to_send ; i + + )
2006-04-04 23:35:07 +02:00
tee_putc ( ( int ) ' ' , PAGER ) ;
2006-03-03 22:26:38 +01:00
2006-04-04 23:35:07 +02:00
for ( i = 0 , p = data ; i < data_length ; i + = 1 , p + = 1 )
2006-03-03 22:26:38 +01:00
{
if ( * p = = ' \0 ' )
tee_putc ( ( int ) ' ' , PAGER ) ;
else
tee_putc ( ( int ) * p , PAGER ) ;
}
2006-04-04 23:35:07 +02:00
if ( ! right_justified )
2006-04-16 23:17:36 +02:00
for ( i = data_length ; i < total_bytes_to_send ; i + + )
2006-04-04 23:35:07 +02:00
tee_putc ( ( int ) ' ' , PAGER ) ;
2006-03-03 22:26:38 +01:00
}
2000-07-31 21:29:14 +02:00
static void
print_table_data_html ( MYSQL_RES * result )
{
2003-01-28 07:38:28 +01:00
MYSQL_ROW cur ;
MYSQL_FIELD * field ;
2000-07-31 21:29:14 +02:00
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 ) ) )
{
2005-01-08 21:25:31 +01:00
ulong * lengths = mysql_fetch_lengths ( 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 + + )
{
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 ) ;
2005-03-07 09:47:24 +01:00
xmlencode_print ( glob_buffer . ptr ( ) , ( int ) strlen ( glob_buffer . ptr ( ) ) ) ;
2007-03-27 10:30:43 +02:00
tee_fputs ( " \" xmlns:xsi= \" http://www.w3.org/2001/XMLSchema-instance \" > " ,
PAGER ) ;
2001-04-11 13:04:03 +02:00
fields = mysql_fetch_fields ( result ) ;
while ( ( cur = mysql_fetch_row ( result ) ) )
{
2005-01-08 21:25:31 +01:00
ulong * lengths = mysql_fetch_lengths ( result ) ;
2001-04-11 13:04:03 +02:00
( void ) tee_fputs ( " \n <row> \n " , PAGER ) ;
for ( uint i = 0 ; i < mysql_num_fields ( result ) ; i + + )
{
2005-01-25 23:25:40 +01:00
tee_fprintf ( PAGER , " \t <field name= \" " ) ;
2005-03-16 08:51:57 +01:00
xmlencode_print ( fields [ i ] . name , ( uint ) strlen ( fields [ i ] . name ) ) ;
2006-09-29 13:29:39 +02:00
if ( cur [ i ] )
{
tee_fprintf ( PAGER , " \" > " ) ;
xmlencode_print ( cur [ i ] , lengths [ i ] ) ;
tee_fprintf ( PAGER , " </field> \n " ) ;
}
else
tee_fprintf ( PAGER , " \" xsi:nil= \" true \" /> \n " ) ;
2001-04-11 13:04:03 +02:00
}
( 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 ) ) )
{
2003-02-08 00:00:35 +01:00
uint length = field - > name_length ;
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
}
}
}
2005-06-01 15:35:09 +02:00
2005-04-05 15:30:17 +02:00
/* print_warnings should be called right after executing a statement */
2005-06-01 15:35:09 +02:00
static void print_warnings ( )
2005-04-05 15:30:17 +02:00
{
2005-06-01 15:35:09 +02:00
const char * query ;
2005-04-05 15:30:17 +02:00
MYSQL_RES * result ;
MYSQL_ROW cur ;
2005-06-01 15:35:09 +02:00
my_ulonglong num_rows ;
2005-04-05 15:30:17 +02:00
/* Get the warnings */
2005-06-01 15:35:09 +02:00
query = " show warnings " ;
2009-02-10 23:47:54 +01:00
mysql_real_query_for_lazy ( query , ( uint ) strlen ( query ) ) ;
2005-04-05 15:30:17 +02:00
mysql_store_result_for_lazy ( & result ) ;
/* Bail out when no warnings */
2005-06-01 15:35:09 +02:00
if ( ! ( num_rows = mysql_num_rows ( result ) ) )
2005-04-05 15:30:17 +02:00
{
mysql_free_result ( result ) ;
return ;
}
/* Print the warnings */
while ( ( cur = mysql_fetch_row ( result ) ) )
{
2005-04-08 16:54:50 +02:00
tee_fprintf ( PAGER , " %s (Code %s): %s \n " , cur [ 0 ] , cur [ 1 ] , cur [ 2 ] ) ;
2005-04-05 15:30:17 +02:00
}
mysql_free_result ( result ) ;
}
2001-12-14 16:43:18 +01:00
2005-06-01 15:35:09 +02:00
static const char * array_value ( const char * * array , char key )
2001-12-14 16:43:18 +01:00
{
2005-06-01 15:35:09 +02:00
for ( ; * array ; array + = 2 )
if ( * * array = = key )
return array [ 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 ;
2003-03-16 08:20:45 +01:00
if ( use_mb ( charset_info ) & &
( l = my_ismbchar ( charset_info , pos , end ) ) )
2002-08-30 11:40:40 +02:00
{
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 ;
2003-03-16 08:20:45 +01:00
while ( my_isspace ( 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 */
2003-03-16 08:20:45 +01:00
while ( my_isspace ( 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 */
2003-03-16 08:20:45 +01:00
while ( end > file_name & & ( my_isspace ( charset_info , end [ - 1 ] ) | |
my_iscntrl ( 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 ;
}
2003-01-28 07:38:28 +01:00
init_tee ( 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
*/
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
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 ;
2004-01-14 03:58:37 +01:00
/* Skip spaces in front of the pager command */
while ( my_isspace ( charset_info , * line ) )
2000-11-17 13:33:29 +01:00
line + + ;
2004-01-14 03:58:37 +01:00
/* Skip the pager command */
param = strchr ( line , ' ' ) ;
/* Skip the spaces between the command and the argument */
while ( param & & my_isspace ( charset_info , * param ) )
param + + ;
if ( ! param | | ! strlen ( param ) ) // if pager was not given, use the default
2000-11-17 13:33:29 +01:00
{
2004-01-14 03:58:37 +01:00
if ( ! default_pager_set )
2000-11-17 13:33:29 +01:00
{
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
{
2004-01-14 03:58:37 +01:00
end = strmake ( pager_name , param , sizeof ( pager_name ) - 1 ) ;
2003-03-16 08:20:45 +01:00
while ( end > pager_name & & ( my_isspace ( charset_info , end [ - 1 ] ) | |
my_iscntrl ( 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 ;
2004-01-14 03:58:37 +01:00
tee_fprintf ( stdout , " PAGER set to '%s' \n " , pager ) ;
2000-11-17 13:33:29 +01:00
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 ;
2004-01-14 03:58:37 +01:00
PAGER = stdout ;
2000-11-17 13:33:29 +01:00
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
*/
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
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 ) ) )
{
2004-05-25 21:00:14 +02:00
/* let the screen auto close on a normal shutdown */
NETWARE_SET_SCREEN_MODE ( SCR_AUTOCLOSE_ON_EXIT ) ;
2000-07-31 21:29:14 +02:00
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
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
2001-11-06 22:00:03 +01:00
static int
com_shell ( String * buffer , char * line __attribute__ ( ( unused ) ) )
{
char * shell_cmd ;
2004-05-06 16:15:46 +02:00
/* Skip space from line begin */
2004-05-18 09:56:45 +02:00
while ( my_isspace ( charset_info , * line ) )
2004-05-06 16:15:46 +02:00
line + + ;
2001-11-06 22:00:03 +01:00
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 )
{
2002-12-25 22:57:01 +01:00
char * tmp , buff [ 256 ] ;
2006-12-14 23:51:37 +01:00
bool save_rehash = opt_rehash ;
2000-07-31 21:29:14 +02:00
int error ;
2002-12-25 22:57:01 +01:00
bzero ( buff , sizeof ( buff ) ) ;
2000-07-31 21:29:14 +02:00
if ( buffer )
{
2006-10-26 19:51:29 +02:00
/*
Two null bytes are needed in the end of buff to allow
get_arg to find end of string the second time it ' s called .
*/
2007-11-26 09:13:23 +01:00
tmp = strmake ( buff , line , sizeof ( buff ) - 2 ) ;
# ifdef EXTRA_DEBUG
tmp [ 1 ] = 0 ;
# endif
2002-12-25 22:57:01 +01:00
tmp = get_arg ( buff , 0 ) ;
if ( tmp & & * tmp )
2000-07-31 21:29:14 +02:00
{
2002-12-25 22:57:01 +01:00
my_free ( current_db , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
current_db = my_strdup ( tmp , MYF ( MY_WME ) ) ;
tmp = get_arg ( buff , 1 ) ;
if ( tmp )
2000-07-31 21:29:14 +02:00
{
my_free ( current_host , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
current_host = my_strdup ( tmp , MYF ( MY_WME ) ) ;
}
}
else
2006-12-14 23:51:37 +01:00
{
/* Quick re-connect */
opt_rehash = 0 ; /* purecov: tested */
}
2000-07-31 21:29:14 +02:00
buffer - > length ( 0 ) ; // command used
}
else
2006-12-14 23:51:37 +01:00
opt_rehash = 0 ;
2000-07-31 21:29:14 +02:00
error = sql_connect ( current_host , current_db , current_user , opt_password , 0 ) ;
2006-12-14 23:51:37 +01:00
opt_rehash = save_rehash ;
2000-07-31 21:29:14 +02:00
if ( connected )
{
2003-12-12 22:18:48 +01:00
sprintf ( buff , " Connection id: %lu " , mysql_thread_id ( & mysql ) ) ;
2000-07-31 21:29:14 +02:00
put_info ( buff , INFO_INFO ) ;
2005-01-14 22:46:04 +01:00
sprintf ( buff , " Current database: %.128s \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 */
2003-03-16 08:20:45 +01:00
while ( my_isspace ( 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 ) ;
2003-03-16 08:20:45 +01:00
while ( my_isspace ( charset_info , * param ) )
2000-07-31 21:29:14 +02:00
param + + ;
end = strmake ( source_name , param , sizeof ( source_name ) - 1 ) ;
2003-03-16 08:20:45 +01:00
while ( end > source_name & & ( my_isspace ( charset_info , end [ - 1 ] ) | |
my_iscntrl ( 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 ) ;
}
2009-03-18 09:18:24 +01:00
if ( ! ( line_buff = batch_readline_init ( MAX_BATCH_BUFFER_SIZE , sql_file ) ) )
2000-07-31 21:29:14 +02:00
{
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
2005-08-09 21:17:28 +02:00
error = read_and_execute ( false ) ;
2000-07-31 21:29:14 +02:00
status = old_status ; // Continue as before
my_fclose ( sql_file , MYF ( 0 ) ) ;
batch_readline_end ( line_buff ) ;
return error ;
}
2003-04-23 02:29:03 +02:00
/* ARGSUSED */
static int
com_delimiter ( String * buffer __attribute__ ( ( unused ) ) , char * line )
{
char buff [ 256 ] , * tmp ;
strmake ( buff , line , sizeof ( buff ) - 1 ) ;
tmp = get_arg ( buff , 0 ) ;
if ( ! tmp | | ! * tmp )
{
put_info ( " DELIMITER must be followed by a 'delimiter' character or string " ,
INFO_ERROR ) ;
return 0 ;
}
2006-10-02 17:45:48 +02:00
else
{
if ( strstr ( tmp , " \\ " ) )
{
put_info ( " DELIMITER cannot contain a backslash character " , INFO_ERROR ) ;
return 0 ;
}
}
2003-04-23 02:29:03 +02:00
strmake ( delimiter , tmp , sizeof ( delimiter ) - 1 ) ;
2005-03-07 09:47:24 +01:00
delimiter_length = ( int ) strlen ( delimiter ) ;
2003-11-20 13:33:07 +01:00
delimiter_str = delimiter ;
2003-04-23 02:29:03 +02:00
return 0 ;
}
2000-07-31 21:29:14 +02:00
/* ARGSUSED */
static int
com_use ( String * buffer __attribute__ ( ( unused ) ) , char * line )
{
2004-01-05 20:45:14 +01:00
char * tmp , buff [ FN_REFLEN + 1 ] ;
2006-05-24 13:10:25 +02:00
int select_db ;
2000-07-31 21:29:14 +02:00
2002-12-25 22:57:01 +01:00
bzero ( buff , sizeof ( buff ) ) ;
2006-08-29 11:38:02 +02:00
strmake ( buff , line , sizeof ( buff ) - 1 ) ;
2002-12-25 22:57:01 +01:00
tmp = get_arg ( buff , 0 ) ;
2002-12-11 15:03:50 +01:00
if ( ! tmp | | ! * tmp )
2000-07-31 21:29:14 +02:00
{
2002-12-11 15:03:50 +01:00
put_info ( " USE must be followed by a database name " , INFO_ERROR ) ;
2000-07-31 21:29:14 +02:00
return 0 ;
}
2004-09-06 13:48:11 +02:00
/*
We need to recheck the current database , because it may change
under our feet , for example if DROP DATABASE or RENAME DATABASE
( latter one not yet available by the time the comment was written )
2004-01-05 20:45:14 +01:00
*/
2004-10-21 14:02:24 +02:00
get_current_db ( ) ;
2004-09-06 13:48:11 +02:00
2004-09-07 22:10:15 +02:00
if ( ! current_db | | cmp_database ( charset_info , current_db , tmp ) )
2000-07-31 21:29:14 +02:00
{
if ( one_database )
2006-05-24 13:10:25 +02:00
{
2002-04-02 19:29:53 +02:00
skip_updates = 1 ;
2006-05-24 13:10:25 +02:00
select_db = 0 ; // don't do mysql_select_db()
}
2000-07-31 21:29:14 +02:00
else
2006-05-24 13:10:25 +02:00
select_db = 2 ; // do mysql_select_db() and build_completion_hash()
}
else
{
/*
USE to the current db specified .
We do need to send mysql_select_db ( ) to make server
update database level privileges , which might
change since last USE ( see bug # 10979 ) .
For performance purposes , we ' ll skip rebuilding of completion hash .
*/
skip_updates = 0 ;
select_db = 1 ; // do only mysql_select_db(), without completion
}
if ( select_db )
{
/*
reconnect once if connection is down or if connection was found to
be down during query
*/
if ( ! connected & & reconnect ( ) )
2003-03-01 23:34:34 +01:00
return opt_reconnect ? - 1 : 1 ; // Fatal error
2006-05-24 13:10:25 +02:00
if ( mysql_select_db ( & mysql , tmp ) )
{
if ( mysql_errno ( & mysql ) ! = CR_SERVER_GONE_ERROR )
return put_error ( & mysql ) ;
2000-07-31 21:29:14 +02:00
2006-05-24 13:10:25 +02:00
if ( reconnect ( ) )
2003-03-01 23:34:34 +01:00
return opt_reconnect ? - 1 : 1 ; // Fatal error
2006-05-24 13:10:25 +02:00
if ( mysql_select_db ( & mysql , tmp ) )
return put_error ( & mysql ) ;
}
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
2006-05-24 13:10:25 +02:00
if ( select_db > 1 )
2006-12-14 23:51:37 +01:00
build_completion_hash ( opt_rehash , 1 ) ;
2000-07-31 21:29:14 +02:00
# endif
}
2006-05-24 13:10:25 +02:00
2000-07-31 21:29:14 +02:00
put_info ( " Database changed " , INFO_INFO ) ;
return 0 ;
}
2005-04-05 15:30:17 +02:00
static int
com_warnings ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
{
show_warnings = 1 ;
2005-04-14 15:07:08 +02:00
put_info ( " Show warnings enabled. " , INFO_INFO ) ;
2005-04-05 15:30:17 +02:00
return 0 ;
}
static int
com_nowarnings ( String * buffer __attribute__ ( ( unused ) ) ,
char * line __attribute__ ( ( unused ) ) )
{
show_warnings = 0 ;
2005-04-14 15:07:08 +02:00
put_info ( " Show warnings disabled. " , INFO_INFO ) ;
2005-04-05 15:30:17 +02:00
return 0 ;
}
2000-07-31 21:29:14 +02:00
2002-12-25 22:57:01 +01:00
/*
Gets argument from a command on the command line . If get_next_arg is
not defined , skips the command and returns the first argument . The
line is modified by adding zero to the end of the argument . If
get_next_arg is defined , then the function searches for end of string
first , after found , returns the next argument and adds zero to the
end . If you ever wish to use this feature , remember to initialize all
items in the array to zero first .
*/
char * get_arg ( char * line , my_bool get_next_arg )
2002-12-11 15:03:50 +01:00
{
2003-04-23 02:29:03 +02:00
char * ptr , * start ;
2002-12-11 15:03:50 +01:00
my_bool quoted = 0 , valid_arg = 0 ;
2003-01-18 15:39:21 +01:00
char qtype = 0 ;
2002-12-11 15:03:50 +01:00
ptr = line ;
2002-12-25 22:57:01 +01:00
if ( get_next_arg )
{
2003-04-23 02:29:03 +02:00
for ( ; * ptr ; ptr + + ) ;
if ( * ( ptr + 1 ) )
2002-12-25 22:57:01 +01:00
ptr + + ;
}
else
{
/* skip leading white spaces */
2003-03-16 08:20:45 +01:00
while ( my_isspace ( charset_info , * ptr ) )
2002-12-25 22:57:01 +01:00
ptr + + ;
if ( * ptr = = ' \\ ' ) // short command was used
ptr + = 2 ;
2004-09-03 17:56:24 +02:00
else
while ( * ptr & & ! my_isspace ( charset_info , * ptr ) ) // skip command
ptr + + ;
2002-12-25 22:57:01 +01:00
}
2003-03-12 20:43:40 +01:00
if ( ! * ptr )
return NullS ;
2003-03-16 08:20:45 +01:00
while ( my_isspace ( charset_info , * ptr ) )
2002-12-11 15:03:50 +01:00
ptr + + ;
2003-01-18 15:39:21 +01:00
if ( * ptr = = ' \' ' | | * ptr = = ' \" ' | | * ptr = = ' ` ' )
2002-12-11 15:03:50 +01:00
{
2003-01-18 15:39:21 +01:00
qtype = * ptr ;
2002-12-11 15:03:50 +01:00
quoted = 1 ;
ptr + + ;
}
2003-04-23 02:29:03 +02:00
for ( start = ptr ; * ptr ; ptr + + )
2002-12-11 15:03:50 +01:00
{
2003-04-23 02:29:03 +02:00
if ( * ptr = = ' \\ ' & & ptr [ 1 ] ) // escaped character
2002-12-11 15:03:50 +01:00
{
2003-04-23 02:29:03 +02:00
// Remove the backslash
strmov ( ptr , ptr + 1 ) ;
2002-12-11 15:03:50 +01:00
}
2003-01-18 15:39:21 +01:00
else if ( ( ! quoted & & * ptr = = ' ' ) | | ( quoted & & * ptr = = qtype ) )
2002-12-11 15:03:50 +01:00
{
* ptr = 0 ;
break ;
}
}
2003-04-23 02:29:03 +02:00
valid_arg = ptr ! = start ;
return valid_arg ? start : NullS ;
2002-12-11 15:03:50 +01:00
}
2000-07-31 21:29:14 +02:00
static int
sql_real_connect ( char * host , char * database , char * user , char * password ,
uint silent )
{
2003-12-18 00:13:52 +01:00
if ( connected )
{
connected = 0 ;
mysql_close ( & mysql ) ;
}
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 ) ;
2003-11-28 11:11:44 +01:00
if ( opt_secure_auth )
mysql_options ( & mysql , MYSQL_SECURE_AUTH , ( char * ) & opt_secure_auth ) ;
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 ) ;
2006-04-18 17:58:27 +02:00
mysql_options ( & mysql , MYSQL_OPT_SSL_VERIFY_SERVER_CERT ,
( char * ) & opt_ssl_verify_server_cert ) ;
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 ) ;
}
2003-08-18 23:08:08 +02:00
if ( default_charset_used )
mysql_options ( & mysql , MYSQL_SET_CHARSET_NAME , default_charset ) ;
2002-04-02 19:29:53 +02:00
if ( ! mysql_real_connect ( & mysql , host , user , password ,
database , opt_mysql_port , opt_mysql_unix_port ,
2003-11-18 12:47:27 +01:00
connect_flag | CLIENT_MULTI_STATEMENTS ) )
2000-07-31 21:29:14 +02:00
{
if ( ! silent | |
( mysql_errno ( & mysql ) ! = CR_CONN_HOST_ERROR & &
mysql_errno ( & mysql ) ! = CR_CONNECTION_ERROR ) )
{
2003-06-04 17:28:51 +02:00
( void ) put_error ( & mysql ) ;
2000-07-31 21:29:14 +02:00
( void ) fflush ( stdout ) ;
return ignore_errors ? - 1 : 1 ; // Abort
}
return - 1 ; // Retryable
}
connected = 1 ;
2002-12-16 14:33:29 +01:00
# ifndef EMBEDDED_LIBRARY
2000-07-31 21:29:14 +02:00
mysql . reconnect = info_flag ? 1 : 0 ; // We want to know if this happens
2004-12-09 14:44:10 +01:00
# else
mysql . reconnect = 1 ;
2002-12-16 14:33:29 +01:00
# endif
2000-07-31 21:29:14 +02:00
# ifdef HAVE_READLINE
2006-12-14 23:51:37 +01:00
build_completion_hash ( opt_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 ) ) )
{
2006-12-14 23:51:37 +01:00
const char * status_str ;
char buff [ 40 ] ;
2004-02-05 10:22:08 +01:00
ulonglong id ;
2004-09-13 09:51:08 +02:00
MYSQL_RES * result ;
LINT_INIT ( result ) ;
2004-02-05 10:22:08 +01:00
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 )
{
2004-09-15 07:06:30 +02:00
tee_fprintf ( stdout , " \n Connection id: \t \t %lu \n " , mysql_thread_id ( & mysql ) ) ;
2004-09-15 10:26:47 +02:00
/*
Don ' t remove " limit 1 " ,
it is protection againts SQL_SELECT_LIMIT = 0
*/
2004-09-15 07:06:30 +02:00
if ( ! mysql_query ( & mysql , " select DATABASE(), USER() limit 1 " ) & &
( result = mysql_use_result ( & mysql ) ) )
{
MYSQL_ROW cur = mysql_fetch_row ( result ) ;
if ( cur )
{
tee_fprintf ( stdout , " Current database: \t %s \n " , cur [ 0 ] ? cur [ 0 ] : " " ) ;
tee_fprintf ( stdout , " Current user: \t \t %s \n " , cur [ 1 ] ) ;
}
mysql_free_result ( result ) ;
}
2002-04-22 22:36:34 +02:00
# ifdef HAVE_OPENSSL
2006-12-14 23:51:37 +01:00
if ( ( status_str = mysql_get_ssl_cipher ( & mysql ) ) )
2002-05-31 11:34:47 +02:00
tee_fprintf ( stdout , " SSL: \t \t \t Cipher in use is %s \n " ,
2006-12-14 23:51:37 +01:00
status_str ) ;
2002-04-22 22:36:34 +02:00
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 ) ;
}
2003-01-28 07:38:28 +01:00
# ifdef USE_POPEN
2000-11-17 13:33:29 +01:00
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
2003-04-23 02:29:03 +02:00
tee_fprintf ( stdout , " Using delimiter: \t %s \n " , delimiter ) ;
2006-09-29 20:52:48 +02:00
tee_fprintf ( stdout , " Server version: \t \t %s \n " , server_version_string ( & mysql ) ) ;
2000-11-17 13:33:29 +01:00
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 ) ) ;
2004-02-05 10:22:08 +01:00
if ( ( id = mysql_insert_id ( & mysql ) ) )
tee_fprintf ( stdout , " Insert id: \t \t %s \n " , llstr ( id , buff ) ) ;
2006-09-29 20:52:48 +02:00
/* "limit 1" is protection against SQL_SELECT_LIMIT=0 */
2004-09-15 10:26:47 +02:00
if ( ! mysql_query ( & mysql , " select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1 " ) & &
2004-09-13 09:51:08 +02:00
( result = mysql_use_result ( & mysql ) ) )
{
MYSQL_ROW cur = mysql_fetch_row ( result ) ;
if ( cur )
{
2005-02-22 11:51:23 +01:00
tee_fprintf ( stdout , " Server characterset: \t %s \n " , cur [ 2 ] ? cur [ 2 ] : " " ) ;
2004-09-13 09:51:08 +02:00
tee_fprintf ( stdout , " Db characterset: \t %s \n " , cur [ 3 ] ? cur [ 3 ] : " " ) ;
2005-02-22 11:51:23 +01:00
tee_fprintf ( stdout , " Client characterset: \t %s \n " , cur [ 0 ] ? cur [ 0 ] : " " ) ;
2004-09-13 09:51:08 +02:00
tee_fprintf ( stdout , " Conn. characterset: \t %s \n " , cur [ 1 ] ? cur [ 1 ] : " " ) ;
}
mysql_free_result ( result ) ;
}
2004-09-15 07:06:30 +02:00
else
{
/* Probably pre-4.1 server */
tee_fprintf ( stdout , " Client characterset: \t %s \n " , charset_info - > csname ) ;
tee_fprintf ( stdout , " Server characterset: \t %s \n " , mysql . charset - > csname ) ;
}
2004-09-13 09:51:08 +02:00
2002-12-16 14:33:29 +01:00
# ifndef EMBEDDED_LIBRARY
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 " ) ;
2002-12-16 14:33:29 +01:00
# endif
2000-11-28 03:47:47 +01:00
2006-12-14 23:51:37 +01:00
if ( ( status_str = mysql_stat ( & mysql ) ) & & ! mysql_error ( & mysql ) [ 0 ] )
2000-07-31 21:29:14 +02:00
{
ulong sec ;
2006-12-14 23:51:37 +01:00
const char * pos = strchr ( status_str , ' ' ) ;
2002-07-23 17:31:22 +02:00
/* print label */
2006-12-14 23:51:37 +01:00
tee_fprintf ( stdout , " %.*s \t \t \t " , ( int ) ( pos - status_str ) , status_str ) ;
if ( ( status_str = str2int ( pos , 10 , 0 , LONG_MAX , ( long * ) & sec ) ) )
2000-07-31 21:29:14 +02:00
{
nice_time ( ( double ) sec , buff , 0 ) ;
2000-11-17 13:33:29 +01:00
tee_puts ( buff , stdout ) ; /* print nice time */
2006-12-14 23:51:37 +01:00
while ( * status_str = = ' ' )
status_str + + ; /* to next info */
2000-11-18 16:34:15 +01:00
tee_putc ( ' \n ' , stdout ) ;
2006-12-14 23:51:37 +01:00
tee_puts ( status_str , 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 ;
}
2006-09-29 20:52:48 +02:00
static const char *
2006-12-14 23:51:37 +01:00
server_version_string ( MYSQL * con )
2006-09-29 20:52:48 +02:00
{
static char buf [ MAX_SERVER_VERSION_LENGTH ] = " " ;
/* Only one thread calls this, so no synchronization is needed */
if ( buf [ 0 ] = = ' \0 ' )
{
char * bufp = buf ;
MYSQL_RES * result ;
2006-12-14 23:51:37 +01:00
bufp = strnmov ( buf , mysql_get_server_info ( con ) , sizeof buf ) ;
2006-09-29 20:52:48 +02:00
/* "limit 1" is protection against SQL_SELECT_LIMIT=0 */
2006-12-14 23:51:37 +01:00
if ( ! mysql_query ( con , " select @@version_comment limit 1 " ) & &
( result = mysql_use_result ( con ) ) )
2006-09-29 20:52:48 +02:00
{
MYSQL_ROW cur = mysql_fetch_row ( result ) ;
if ( cur & & cur [ 0 ] )
{
2009-02-10 23:47:54 +01:00
bufp = strxnmov ( bufp , ( uint ) ( sizeof buf - ( bufp - buf ) ) , " " , cur [ 0 ] ,
NullS ) ;
2006-09-29 20:52:48 +02:00
}
mysql_free_result ( result ) ;
}
/* str*nmov doesn't guarantee NUL-termination */
if ( bufp = = buf + sizeof buf )
buf [ sizeof buf - 1 ] = ' \0 ' ;
}
return buf ;
}
2000-07-31 21:29:14 +02:00
static int
2003-06-04 17:28:51 +02:00
put_info ( const char * str , INFO_TYPE info_type , uint error , const char * sqlstate )
2000-07-31 21:29:14 +02:00
{
2003-04-03 18:55:37 +02:00
FILE * file = ( info_type = = INFO_ERROR ? stderr : stdout ) ;
2000-07-31 21:29:14 +02:00
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 )
{
2003-04-03 18:55:37 +02:00
( void ) fflush ( file ) ;
fprintf ( file , " ERROR " ) ;
2000-07-31 21:29:14 +02:00
if ( error )
2004-09-08 20:28:11 +02:00
{
if ( sqlstate )
( void ) fprintf ( file , " %d (%s) " , error , sqlstate ) ;
else
( void ) fprintf ( file , " %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
{
2003-04-03 18:55:37 +02:00
( void ) fprintf ( file , " at line %lu " , status . query_start_line ) ;
2000-07-31 21:29:14 +02:00
if ( status . file_name )
2003-04-03 18:55:37 +02:00
( void ) fprintf ( file , " in file: '%s' " , status . file_name ) ;
2000-07-31 21:29:14 +02:00
}
2003-04-03 18:55:37 +02:00
( void ) fprintf ( file , " : %s \n " , str ) ;
( void ) fflush ( file ) ;
2000-07-31 21:29:14 +02:00
if ( ! ignore_errors )
return 1 ;
}
else if ( info_type = = INFO_RESULT & & verbose > 1 )
2003-04-03 18:55:37 +02:00
tee_puts ( str , file ) ;
2000-07-31 21:29:14 +02:00
if ( unbuffered )
2003-04-03 18:55:37 +02:00
fflush ( file ) ;
2000-07-31 21:29:14 +02:00
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 )
2006-04-04 23:35:07 +02:00
putchar ( ' \a ' ) ; /* This should make a bell */
2000-07-31 21:29:14 +02:00
vidattr ( A_STANDOUT ) ;
if ( error )
2003-06-04 17:28:51 +02:00
{
if ( sqlstate )
( void ) tee_fprintf ( file , " ERROR %d (%s): " , error , sqlstate ) ;
else
( void ) tee_fprintf ( file , " ERROR %d: " , error ) ;
}
2000-07-31 21:29:14 +02:00
else
2003-04-03 18:55:37 +02:00
tee_puts ( " ERROR: " , file ) ;
2000-07-31 21:29:14 +02:00
}
else
vidattr ( A_BOLD ) ;
2003-04-03 18:55:37 +02:00
( void ) tee_puts ( str , file ) ;
2000-07-31 21:29:14 +02:00
vidattr ( A_NORMAL ) ;
}
if ( unbuffered )
2003-04-03 18:55:37 +02:00
fflush ( file ) ;
2000-07-31 21:29:14 +02:00
return info_type = = INFO_ERROR ? - 1 : 0 ;
}
2000-11-17 13:33:29 +01:00
2003-06-04 17:28:51 +02:00
static int
2006-12-14 23:51:37 +01:00
put_error ( MYSQL * con )
2003-06-04 17:28:51 +02:00
{
2006-12-14 23:51:37 +01:00
return put_info ( mysql_error ( con ) , INFO_ERROR , mysql_errno ( con ) ,
mysql_sqlstate ( con ) ) ;
2003-06-04 17:28:51 +02: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 ( ) ;
2003-03-16 08:20:45 +01:00
while ( start < end & & ! my_isgraph ( 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 ;
2004-05-25 21:00:14 +02:00
NETWARE_YIELD ;
2000-11-17 13:33:29 +01:00
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
2005-03-16 01:37:05 +01:00
va_end ( args ) ;
2000-11-17 13:33:29 +01:00
if ( opt_outfile )
2005-03-16 01:37:05 +01:00
{
va_start ( args , fmt ) ;
2000-11-18 01:15:06 +01:00
( void ) vfprintf ( OUTFILE , fmt , args ) ;
2005-03-16 01:37:05 +01:00
va_end ( args ) ;
}
2000-11-17 13:33:29 +01:00
}
void tee_fputs ( const char * s , FILE * file )
{
2004-05-25 21:00:14 +02:00
NETWARE_YIELD ;
2000-11-17 13:33:29 +01:00
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 )
{
2004-05-25 21:00:14 +02:00
NETWARE_YIELD ;
2000-11-17 13:33:29 +01:00
fputs ( s , file ) ;
2006-09-29 20:52:48 +02:00
fputc ( ' \n ' , file ) ;
2001-08-22 00:45:07 +02:00
# ifdef OS2
2006-09-29 20:52:48 +02:00
fflush ( file ) ;
2001-08-22 00:45:07 +02:00
# endif
2000-11-17 13:33:29 +01:00
if ( opt_outfile )
{
fputs ( s , OUTFILE ) ;
2006-09-29 20:52:48 +02:00
fputc ( ' \n ' , OUTFILE ) ;
2000-11-17 13:33:29 +01:00
}
}
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 ) ;
}
2003-01-28 07:38:28 +01:00
# if defined( __WIN__) || defined( OS2) || defined(__NETWARE__)
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 )
{
2003-01-28 07:38:28 +01:00
# if defined( __WIN__) || defined( OS2) || defined(__NETWARE__)
2000-07-31 21:29:14 +02:00
return clock ( ) ;
# else
struct tms tms_tmp ;
return times ( & tms_tmp ) ;
# endif
}
2008-01-25 16:53:21 +01:00
/**
Write as many as 52 + 1 bytes to buff , in the form of a legible duration of time .
len ( " 4294967296 days, 23 hours, 59 minutes, 60.00 seconds " ) - > 52
*/
2000-07-31 21:29:14 +02:00
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 ;
2004-05-27 15:54:40 +02:00
buff = int10_to_str ( ( long ) tmp , buff , 10 ) ;
2000-07-31 21:29:14 +02:00
buff = strmov ( buff , tmp > 1 ? " days " : " day " ) ;
}
if ( sec > = 3600.0 )
{
tmp = ( ulong ) floor ( sec / 3600.0 ) ;
sec - = 3600.0 * tmp ;
2004-05-27 15:54:40 +02:00
buff = int10_to_str ( ( long ) tmp , buff , 10 ) ;
2000-07-31 21:29:14 +02:00
buff = strmov ( buff , tmp > 1 ? " hours " : " hour " ) ;
}
if ( sec > = 60.0 )
{
tmp = ( ulong ) floor ( sec / 60.0 ) ;
sec - = 60.0 * tmp ;
2004-05-27 15:54:40 +02:00
buff = int10_to_str ( ( long ) tmp , buff , 10 ) ;
2000-07-31 21:29:14 +02:00
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 ( )
{
2003-07-03 10:55:36 +02:00
processed_prompt . free ( ) ; // Erase the old prompt
time_t lclock = time ( NULL ) ; // Get the date struct
2002-04-03 12:36:01 +02:00
struct tm * t = localtime ( & lclock ) ;
2003-07-03 10:55:36 +02:00
/* 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 ' :
2003-07-03 10:55:36 +02:00
c - - ; // stop it from going beyond if ends with %
2002-04-03 12:36:01 +02:00
break ;
case ' c ' :
add_int_to_prompt ( + + prompt_counter ) ;
break ;
case ' v ' :
2003-05-27 15:40:14 +02:00
if ( connected )
processed_prompt . append ( mysql_get_server_info ( & mysql ) ) ;
else
processed_prompt . append ( " not_connected " ) ;
2002-04-03 12:36:01 +02:00
break ;
case ' d ' :
processed_prompt . append ( current_db ? current_db : " (none) " ) ;
break ;
case ' h ' :
{
2003-05-27 15:40:14 +02:00
const char * prompt ;
prompt = connected ? mysql_get_host_info ( & mysql ) : " not_connected " ;
2002-04-03 12:36:01 +02:00
if ( strstr ( prompt , " Localhost " ) )
processed_prompt . append ( " localhost " ) ;
else
{
const char * end = strcend ( prompt , ' ' ) ;
processed_prompt . append ( prompt , ( uint ) ( end - prompt ) ) ;
}
break ;
}
case ' p ' :
2005-01-16 06:19:34 +01:00
{
2002-12-16 14:33:29 +01:00
# ifndef EMBEDDED_LIBRARY
2003-05-27 15:40:14 +02:00
if ( ! connected )
{
processed_prompt . append ( " not_connected " ) ;
break ;
}
2005-01-16 06:19:34 +01:00
const char * host_info = mysql_get_host_info ( & mysql ) ;
if ( strstr ( host_info , " memory " ) )
{
processed_prompt . append ( mysql . host ) ;
}
else if ( strstr ( host_info , " TCP/IP " ) | |
2003-06-04 18:21:51 +02:00
! mysql . unix_socket )
2002-04-03 12:36:01 +02:00
add_int_to_prompt ( mysql . port ) ;
else
2003-02-02 04:13:09 +01:00
{
char * pos = strrchr ( mysql . unix_socket , ' / ' ) ;
2003-02-04 20:52:14 +01:00
processed_prompt . append ( pos ? pos + 1 : mysql . unix_socket ) ;
2003-02-02 04:13:09 +01:00
}
2002-12-16 14:33:29 +01:00
# endif
2005-01-16 06:19:34 +01:00
}
2002-04-03 12:36:01 +02:00
break ;
case ' U ' :
if ( ! full_username )
init_username ( ) ;
2006-07-11 21:42:03 +02:00
processed_prompt . append ( full_username ? full_username :
( current_user ? current_user : " (unknown) " ) ) ;
2002-04-03 12:36:01 +02:00
break ;
case ' u ' :
if ( ! full_username )
init_username ( ) ;
2006-07-11 21:42:03 +02:00
processed_prompt . append ( part_username ? part_username :
( current_user ? current_user : " (unknown) " ) ) ;
2002-04-03 12:36:01 +02:00
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 ' :
2004-03-08 22:52:06 +01:00
if ( t - > tm_hour < 10 )
processed_prompt . append ( ' 0 ' ) ;
2002-04-03 12:36:01 +02:00
add_int_to_prompt ( t - > tm_hour ) ;
break ;
case ' r ' :
int getHour ;
getHour = t - > tm_hour % 12 ;
if ( getHour = = 0 )
getHour = 12 ;
2004-03-08 22:52:06 +01:00
if ( getHour < 10 )
processed_prompt . append ( ' 0 ' ) ;
2002-04-03 12:36:01 +02:00
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 ;
dateTime = ctime ( & lclock ) ;
processed_prompt . append ( strtok ( dateTime , " \n " ) ) ;
break ;
case ' s ' :
2004-03-08 22:52:06 +01:00
if ( t - > tm_sec < 10 )
processed_prompt . append ( ' 0 ' ) ;
2002-04-03 12:36:01 +02:00
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 ;
2006-07-19 20:33:56 +02:00
case ' l ' :
processed_prompt . append ( delimiter_str ) ;
break ;
2002-04-03 12:36:01 +02:00
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 */